Unity AssetsBundle打包

为什么要使用AssetsBundle包

减少安装包的大小

默认情况下,unity编译打包是对项目下的Assets文件夹全部内容进行压缩打包

那么按照这个原理,你的Assets文件夹的大小将会影响到你最终打包出的安装包的大小,假如你现在正在制作一个游戏项目,最终打出来的安装包过大可能会对玩家下载造成一定影响,对一般玩家来讲,下载10M的游戏安装包远远比下载100M的游戏安装包要更容易接受,而AssetBundle可以将一部分资源打包到一个压缩包里面,游戏运行到需要的时候再进行下载这部分资源

游戏一共有100个关卡,如果将这些全部打包则打出的安装包大小为100M,如果现在用AssetBundle技术将后面90关的资源分离出去进行打包,那么你现在打包的游戏内容只有10个关卡的资源,安装包大小仅为10M,等玩家体验了前十关觉得还不错,当他想玩10关以后的游戏内容时,提示他需要下载资源包体验更多精彩内容,然后在unity中加载剩余的90关的资源包。这样做的话,你的游戏安装包仅仅10M大小,因为下载比较快,也比较省流量,可能会吸引更多的玩家下载体验你的游戏

可以用热更新修复游戏的Bug

经历千辛万苦,你的游戏终于上线了,突然收到玩家反馈,游戏第20关通关后无法进入到下一关,据查证,是原来打包时某个同事粗心大意把第21关的资源弄错了,导致加载21关时报错,,我们现在需要第一时间修复这个问题,如果是按照原来的打包方式,需要重新出一个100M的包,然后把重新出的包交给游戏平台审核,审核通过后,玩家需要卸载掉原来的游戏软件,重新下载你们新打出的安装包

如果按照另一种打包方式,我们在后面90关的AssetBundle包里修复这个问题,这时候通过服务器传输AssetBundle最新的包,会把有问题的资源进行修复,提示玩家bug已经修复,玩家进入游戏,发现可以把20关打通了,并且成功进入到下一关了,在这个游戏过程中,玩家不需要重新下载那100M的安装包,只需要打开游戏下载部分需要更新的资源,这部分资源一般会比较小,一般情况下可能是几十k的大小,就可以重新体验游戏了。这就是AssetBundle的第二个作用


AssetsBundle包的打包方式

设置资源标签

需要进行AssetsBundle打包的时候,需要先对要打包的资源的资源标签进行设置

调用Unity官方函数打出AssetsBundle包

对资源打包的设置完成后,通过在代码中调用Unity官方函数的方式,将所有设置了资源标签的资源打出AssetsBundle包

调用的函数为:

public static AssetBundleManifest BuildAssetBundles(string outputPath, BuildAssetBundleOptions assetBundleOptions, BuildTarget targetPlatform)

这个函数的功能为将所有设置了资源标签的资源打出AssetsBundle包

函数一共有三个参数:

第一个参数为打包出来文件的路径

第二个参数为设置打包资源的压缩方式,是枚举变量,其中比较常用的三个为:

BuildAssetBundleOptions.UncompressedAssetBundle:不压缩,包大,加载快

BuildAssetBundleOptions.None:使用LZMA算法压缩,压缩的包更小,但是加载时间更长,需要解压全部。
BuildAssetBundleOptions.ChunkBasedCompression:使用LZ4压缩,压缩率没有LZMA高,但是我们可以加载指定资源而不用解压全部。

这几种压缩方式中,LZ4比较常用

第三个参数为设置打包资源的应用平台,一般都使用

BuildTarget.StandaloneWindows64 //PC端

BuildTarget.Android //安卓端

BuildTarget.iOS //苹果端

示例代码:

BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetBundle", BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);

调用函数改变资源标签

改变资源标签的方式,除了在Unity编辑器中设置之外,还可以使用代码设置资源标签

string path = "Assets/MainPrefab.prefab";
AssetImporter importer = AssetImporter.GetAtPath(path);
importer.assetBundleName = "prefab"
importer.assetBundleVariant = "u3d";

这里面应用到的类是AssetImporter类,这个类型代表了AssetBundole资源。

获取AssetImporter类型变量的方法为AssetImporter.GetAtPath(string)方法

这个方法的参数是传入一个由Assets开头,直到文件的后缀名结束的路径,然后将这个文件AssetsBundle相关属性的AssetImporter类返回

然后通过AssetImporter类的assetBundleName改变文件的资源标签

然后通过AssetImporter类的assetBundleVariant改变文件的资源版本标签


加载AssetBundle包

AssetBundle.LoadFromFile 本地资源加载

通过加载本地文件的形式加载AssetBundle资源,场景适用的情况下效率最高

AssetBundle ab = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundle/1.1");

在方法中传入本地资源路径,最后要以AssetBundle包的文件名和后缀名为止,将路径下的AssetBundle包以AssetBundle类型的变量保存下来

AssetBundle.LoadFromFileAsync 本地资源加载(异步)

上面方法的异步版本,在加载过程中不会因为包体过大导致程序进入未响应,需要用到协程(不会协程用法的自己去网上学一下,或者翻我以前的博客)

    IEnumerator LoadAssetBundle(Action<AssetBundle> action){AssetBundleCreateRequest creat = AssetBundle.LoadFromFileAsync(Application.dataPath + "/AssetBundle/1.1");yield return creat;AssetBundle ab = creat.assetBundle;action(ab);}

AssetBundle.LoadFromFileAsync方法参数与同步版本相同,不过返回值由AssetBundle类型变为了AssetBundleCreateRequest类型,这个类型的变量可以作为yield return等待方法的参数,然后通过assetBundle属性获取AssetBundle类型变量

AssetBundle.LoadFromMemory 从数据流加载

通过数据流读取AssetBundle资源,这个方法读取本地文件的效率不如LoadFromFile,所以不要用这个方法加载本地文件的AssetBundle,这个方法应该大部分应用于通过网络协议传输的数据流上

AssetBundle ab = AssetBundle.LoadFromMemory(File.ReadAllBytes(Application.dataPath + "/AssetBundle/1.1"));

方法的参数为byte数组,返回一个AssetBundle类型的变量

AssetBundle.LoadFromMemoryAsync 从数据流加载(异步)

上述方法的异步版本,通过数据流加载速度相对较慢,比较建议使用异步

    IEnumerator LoadAssetBundle(Action<AssetBundle> action){AssetBundleCreateRequest creat = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(Application.dataPath + "/AssetBundle/1.1"));yield return creat;AssetBundle ab = creat.assetBundle;action(ab);}

与LoadFromFileAsync方法相同,返回一个AssetBundleCreateRequest类型的参数,这个类型的变量可以作为yield return等待方法的参数,然后通过assetBundle属性获取AssetBundle类型变量

UnityWebRequestAssetBundle.GetAssetBundle 从网络获取(异步)

从网址下载AssetBundle包并读取,因为从网络下载的过程都较长,所以这个方法只有异步版本

    IEnumerator LoadAssetBundle(Action<AssetBundle> action){string url = "file://" + Application.dataPath + "/AssetBundle/1.1";UnityWebRequest unityAb = UnityWebRequestAssetBundle.GetAssetBundle(url);yield return unityAb.SendWebRequest();AssetBundle ab = DownloadHandlerAssetBundle.GetContent(unityAb);action(ab);}

方法需要传入一个网址作为参数,将这个参数中的内容下载下来,这里传入了一个本地路径,本地路径也可以作为网址传入,方法返回一个UnityWebRequest类型的变量,这个类型的变量中SendWebRequest方法可以返回一个能够在yield return中应用的值,使协程等待至文件下载完毕,然后通过DownloadHandlerAssetBundle.GetContent方法,传入UnityWebRequest类型的参数,就能够返回AssetBundle类型的变量


从AssetBundle包中获取资源

单纯只是读取到AssetBundle类型的变量是无法直接使用的,需要将AssetBundle类型转换为平时使用的资源类型,比如GameObject,Material。Texture类型

AssetBundle.LoadAsset<>() 从包中读取单个文件

AssetBundle ab = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundle/1.1");
GameObject a = ab.LoadAsset<GameObject>("Cube");

AssetBundle.LoadAsset<>()方法分别有一个泛型类型和一个参数,方法的泛型类型中传入需要从方法中获取的返回值类型,参数为需要获取的类型的名字,上面代码中表示返回AssetBundle包中名为Cube的预设物并保存

AssetBundle.LoadAssetAsync<>() 从包中读取单个文件(异步)

    IEnumerator LoadGameObject(AssetBundle ab , Action<GameObject> action){AssetBundleRequest abr = ab.LoadAssetAsync<GameObject>("Cube");yield return abr;GameObject g = (GameObject)abr.asset;action(g);}

与AssetBundle.LoadAsset<>()方法的泛型和参数应用方式相同,但是返回值为AssetBundleRequest类型,这个类型可以直接传入yield return,并且可以通过asset属性获取保存的资源,不过返回的资源是Object类型,需要进行强制转换

AssetBundle.LoadAllAssets 从包中获取全部文件

AssetBundle ab = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundle/1.1");
UnityEngine.Object[] objs = ab.LoadAllAssets();

AssetBundle.LoadAllAssets 不需要任何参数,返回一个Objcet数组,这个数组包含AssetBundle包中包含的全部资源

AssetBundle.LoadAllAssetsAsync 从包中获取全部文件(异步)

    IEnumerator LoadGameObject(AssetBundle ab , Action<UnityEngine.Object[]> action){AssetBundleRequest abr = ab.LoadAllAssetsAsync();yield return abr;UnityEngine.Object[] objs = ab.LoadAllAssets();action(objs);}

使用方式和LoadAssetAsync相同,只不过是改为了使用LoadAllAssets()方法返回Object数组


卸载AssetBundle资源包

AssetBundle.Unlock 卸载AssetBundle包

        AssetBundle ab = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundle/1.1");ab.Unload(true);

调用AssetBundle类型变量的Unload方法,就能够从内存中卸载AssetBundle包的资源,其中参数的布尔值为是否释放场景中正在使用的AssetBundle包中的资源,一般默认都会传入true作为参数,卸载AssetBundle包时,场景中有涉及到包内资源的物体会报错,所以一般在切换场景或特定情况下使用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/3721.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

没有文件服务器,头像存哪里合适

没有文件服务器&#xff0c;头像存哪里合适 视频在bilibili&#xff1a;没有文件服务器&#xff0c;头像存哪里合适 1. 背景 之前有同学私信我说&#xff0c;他的项目只是想存个头像&#xff0c;没有别的文件存储需求&#xff0c;不想去用什么Fastdfs之类的方案搭建文件服务…

【C++杂货铺】多态

目录 &#x1f308;前言&#x1f308; &#x1f4c1;多态的概念 &#x1f4c1; 多态的定义及实现 &#x1f4c2; 多态的构成条件 &#x1f4c2; 虚函数 &#x1f4c2; 虚函数重写 &#x1f4c2; C11 override 和 final &#x1f4c2; 重载&#xff0c;覆盖&#xff08;重写…

ARM学习(26)链接库的依赖查看

笔者今天来聊一下查看链接库的依赖。 通常情况下&#xff0c;运行一个可执行文件的时候&#xff0c;可能会出现找不到依赖库的情况&#xff0c;比如图下这种情况&#xff0c;可以看到是缺少了license.dll或者libtest.so&#xff0c;所以无法运行。怎么知道它到底缺少什么dll呢&…

HarmonyOS-Next开源三方库 MPChart:打造出色的图表体验

点击下载源码https://download.csdn.net/download/liuhaikang/89228765 简介 随着移动应用的不断发展&#xff0c;数据可视化成为提高用户体验和数据交流的重要手段之一。在 OpenAtom OpenHarmony&#xff08;简称“OpenHarmony”&#xff09;应用开发中&#xff0c;一个强大而…

线性代数:抽象向量空间

一、说明 有些函数系列极具线性代数的向量特征。这里谈及多项式构成函数的线性代数意义。问题是这个主题能展开多少内涵&#xff1f;请看本文的论述。 二、线性空间和向量 让我先问你一个简单的问题。什么是向量&#xff1f;为了方便起见&#xff0c;二维箭头从根本上说是平…

OpenHarmony实战开发—进程间通讯

版本&#xff1a;v3.2 Beta5 进程模型 OpenHarmony的进程模型如下图所示&#xff1a; 应用中&#xff08;同一包名&#xff09;的所有UIAbility、ServiceExtensionAbility、DataShareExtensionAbility运行在同一个独立进程中&#xff0c;即图中绿色部分的“Main Process”。…

python自定义交叉熵损失,再和pytorch api对比

背景 我们知道&#xff0c;交叉熵本质上是两个概率分布之间差异的度量&#xff0c;公式如下 其中概率分布P是基准&#xff0c;我们知道H(P,Q)>0&#xff0c;那么H(P,Q)越小&#xff0c;说明Q约接近P。 损失函数本质上也是为了度量模型和完美模型的差异&#xff0c;因此可以…

网御星云防火墙策略配置

网御星云防火墙配置 1. 初始设定2. 网络配置3. 安全规则和策略4. 监控和维护零基础入门学习路线视频配套资料&国内外网安书籍、文档网络安全面试题 1. 初始设定 接入网络&#xff1a; 在开始配置之前&#xff0c;确保你的网御星云防火墙正确连接到网络。这通常涉及将WAN接…

07 流量回放实现自动化回归测试

在本模块的前四讲里&#xff0c;我向你介绍了可以直接落地的、能够支撑百万并发的读服务的系统架构&#xff0c;包含懒加载缓存、全量缓存&#xff0c;以及数据同步等方案的技术细节。 基于上述方案及细节&#xff0c;你可以直接对你所负责的读服务进行架构升级&#xff0c;将…

【Redis 开发】一人一单,超卖问题(悲观锁,乐观锁,分布式锁)

锁 悲观锁乐观锁第一种&#xff1a;版本号法第二种&#xff1a;CAS法实现乐观锁 悲观锁与乐观锁的比较 一人一单分布式锁Redis实现分布式锁 悲观锁 认为线程问题一定会发生&#xff0c;因此在操作数据库之前先获取锁&#xff0c;确保线程串行执行&#xff0c;例如Synchronized…

51单片机使用两个按钮控制LED灯不同频率的闪烁

#include <reg52.h>sbit button1 P1^1; // 间隔2秒的按钮 sbit button2 P1^5; // 间隔0.6秒的按钮sbit led P1^3;unsigned int cnt1 0; // 设置LED1灯的定时器溢出次数 unsigned int cnt2 0; // 设置LED2灯的定时器溢出次数 unsigned int flg1 0; // 模式1的标识值…

x86 64位的ubuntu环境下汇编(无优化)及函数调用栈的详解

1. 引言 为了深入理解c&#xff0c;决定学习一些简单的汇编语言。使用ubuntu系统下g很容易将一个c的文件编译成汇编语言。本文使用此方法&#xff0c;对一个简单的c文件编译成汇编语言进行理解。 2.示例 文件名&#xff1a;reorder_demo.cpp #include<stdio.h>typede…

强固型车载电脑在智能轨道安全解决方案的应用

智能轨道安全解决方案 信迈提供一系列具有传感、诊断、人工智能和无线功能的车载列车解决方案。它们提供全面的可扩展性和面向未来的车辆、路旁、信号、电力、障碍物检测和数据收集功能。 应用程序: 铁路供电监控车载列车安全保护铁路轨道监控驾驶行为分析 智能车载解决方案…

Django连接数据库

数据库登录命令 mysql -u root -p show databases; Django连接数据库 在settings.py文件中进行配置和修改 DATABASES {default: {ENGINE: django.db.backends.mysql,HOST: 127.0.0.1, # 数据库主机PORT: 3306, # 数据库端口USER: root, # 数据库用户名PASSWORD: 12345…

flutter release 报错 Error: SocketException: Failed host lookup:

flutter 的 debug 模式没有任何问题 &#xff0c;打了release 包后一直报下面的错&#xff0c;查了一下是 因为没有网络权限 Error: SocketException: Failed host lookup: yomi-test-aws-sg.yomigame.games (OS Error: No address associated with hostname, errno 7) 按照下…

win10加入域环境

win10加入域环境 导航 文章目录 win10加入域环境导航一、关闭防火墙二、使客户端的电脑指向于域控服务器三、检验是否加入了域 一、关闭防火墙 在进行加入域服务之前,我们需要先关闭防火墙(为了不必要的麻烦) 按 winr调出运行窗口,输入 control打开控制面板 点击系统和安全点…

python基础之元组、集合和函数的定义与返回值

1.元祖 1.元祖的定义 元组的数据结构跟列表相似 特征&#xff1a;有序、 有序&#xff1a;有&#xff08;索引/下标/index&#xff09; 正序、反序标识符&#xff1a; ( ) 里面的元素是用英文格式的逗号分割开来关键字&#xff1a;tuple 列表和元组有什么区别&#xff1f; 元组…

异常风云:解码 Java 异常机制

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一个人虽可以走的更快&#xff0c;但一群人可以走的更远。 我是一名后…

C语言数据类型的介绍,类型的基本归类,整型在内存中的存储,原码、反码、补码,大小端等介绍

文章目录 前言一、数据类型的介绍类型的意义 1. 类型的基本归类&#xff08;1&#xff09;. 整型家族&#xff08;2&#xff09;. 浮点数家族&#xff08;3&#xff09;. 构造类型&#xff08;4&#xff09;. 指针类型&#xff08;5&#xff09;. 空类型 二、整型在内存中的存储…

[Collection与数据结构] PriorityQueue与堆

1. 优先级队列 1.1 概念 前面介绍过队列&#xff0c;队列是一种先进先出(FIFO)的数据结构&#xff0c;但有些情况下&#xff0c;操作的数据可能带有优先级&#xff0c;一般出队列时&#xff0c;可能需要优先级高的元素先出队列&#xff0c;该中场景下&#xff0c;使用队列显然…