unity Assetbundle 使用

本文的主要内容是分析5.X版本的AssetBundle机制(包括建立资源包、压缩资源包、加载资源包和从资源包中加载/卸载资源等几个方面)及其关键的API使用方式。
AssetBundle是Unity推荐的资源管理方式,官方列举了诸如热更新,压缩,灵活等等优势。算法

 

使用步骤
1、打包
1.经过Editor中的UI为AssetBundle标记资源。并且一个资源和对应的AssetBundle的映射将会在资源数据库(AssetDatabase)中被建立。数据库

 


2.BuildPipeline.BuildAssetBundles():咱们只须要提供一个输出AssetBundle的地址便可。引擎将自动根据资源的assetbundleName属性(即在上文中UI中设置的值)批量打包,自动创建Bundle以及资源之间的依赖关系。
Unity3D为咱们提供了惟一的API用来打AssetBundle包。即:BuildPipeline.BuildAssetBundles
在脚本中调用BuildPipeline.BuildAssetBundles,U3D将自动根据资源的assetbundleName属性批量打包,自动创建Bundle和资源之间的依赖关系。在资源的Inpector界面最下方可设置该资源的assetbundleName,每一个assetbundleName对应一个Bundle,即assetbundleName相同的资源会打在一个Bundle中。若是所依赖的资源设置了不一样的assetbundleName,则会自动与之创建依赖关系,避免出现冗余,从而减少Bundle包的大小。固然,除了能够指定assetbundleName,咱们还能够在Inpector中设置另外一个名字,即variant。在打包时,variant会做为后缀添加在assetbundleName以后。相同assetbundleName,不一样variant的Bundle是能够相互替换的。缓存

设置好以后,咱们只须要建立一个新的脚本,经过编辑器拓展调用BuildPipeline.BuildAssetBundles方法便可:异步

BuildPipeline.BuildAssetBundles方法的参数
outputPath:输出目录,通常咱们设置为  Application.streamingAssetsPath + Bundle的目标路径和Bundle名称
targetPlatform:目标平台,在安卓,IOS,PC下,咱们须要传入不一样的平台标识,以打出不一样平台适用的包,注意,Windows平台下打出来的包,不能用于IOS
BuildAssetBundleOptions:BuildAssetBundleOptions.CollectDependencies会去查找依赖,BuildAssetBundleOptions.CompleteAssets会强制包含整个资源,BuildAssetBundleOptions.DeterministicAssetBundle会确保生成惟一ID,在打包依赖时会有用到编辑器

Unity3D引擎为咱们提供了三种压缩策略来处理AssetBundle的压缩,即:LZMA格式、LZ4格式、不压缩。
LZMA格式:在默认状况下,打包生成的AssetBundle都会被压缩。在U3D中,AssetBundle的标准压缩格式即是LZMA(LZMA是一种序列化流文件),所以在默认状况下,打出的AssetBundle包处于LZMA格式的压缩状态,在使用AssetBundle前须要先解压缩。
使用LZMA格式压缩的AssetBundle的包体积最小(高压缩比),可是相应的会增长解压缩时的时间。
LZ4格式: Unity 5.3以后的版本增长了LZ4格式压缩,因为LZ4的压缩比通常,所以通过压缩后的AssetBundle包体的体积较大(该算法基于chunk)。可是,使用LZ4格式的好处在于解压缩的时间相对要短。若要使用LZ4格式压缩,只须要在打包的时候开启BuildAssetBundleOptions.ChunkBasedCompression便可。
BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath,
BuildAssetBundleOptions.ChunkBasedCompression);
不压缩:咱们也能够不对AssetBundle进行压缩。没有通过压缩的包体积最大,可是访问速度最快。若要使用不压缩的策略,只须要在打包的时候开启BuildAssetBundleOptions.UncompressedAssetBundle便可。
BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath,
BuildAssetBundleOptions.UncompressedAssetBundle);函数

在打包的时候,咱们须要对包的大小和数量进行一个平衡,全部资源打成一个包,一个资源打一个包,都是比较极端的作法,他们的问题也很明显,更多状况下咱们须要灵活地将他们组合起来
打成一个包的缺点是加载了这个包,咱们不须要的东西也会被加载进来,占用额外内存,并且不利于热更新 打成多个包的缺点是,容易形成冗余,首先影响包的读取速度,而后包之间的内容可能会有重复,且太多的包不利于资源管理哪些模块打成一个包,哪些模块打成多个包,须要根据实际状况来,例如游戏中每一个怪物都须要打成一个包,由于每一个怪物之间是独立的,例如游戏的基础UI,能够打成一个包,由于他们在各个界面都会出现
 PS.想打包进AssetBundle中的二进制文件,文件名的后缀必须为“.bytes”ui

2、加载
首先获取AssetBundle对象,第二从AssetBundle中加载目标资源。在运行时加载AssetBundle对象主要能够分为两大类途径:
1.先获取WWW对象,再经过WWW.assetBundle加载AssetBundle对象:
public WWW(string url),直接调用WWW类的构造函数,目标AssetBundle所在的路径做为其参数,构造WWW对象的过程当中会加载Bundle文件并返回一个WWW对象,完成后会在内存中建立较大的WebStream(解压后的内容,一般为原Bundle文件的4~5倍大小,纹理资源比例可能更大),所以后续的AssetBundle.LoadAsset能够直接在内存中进行。
public static WWW LoadFromCacheOrDownload(string url, int version, uint crc = 0),WWW类的一个静态方法,调用该方法一样会加载Bundle文件同时返回一个WWW对象,和上一个直接调用WWW的构造函数的区别在于该方法会将解压形式的Bundle内容存入磁盘中做为缓存(若是该Bundle已在缓存中,则省去这一步),完成后只会在内存中建立较小的SerializedFile,然后续的AssetBundle.LoadAsset须要经过IO从磁盘中的缓存获取。LoadFromCacheOrDownload会记录全部Bundle的使用状况,并在适当的时候删除最近不多使用的资源包,它容许存在两个版本号不一样但名字同样的资源包,这意味着你更新这个资源包以后,若是没有更新代码中的版本号,你可能取到的会是旧版本的资源包,从而产生其余的一些BUG。另外,当你的磁盘空间不足的时候(硬盘爆了),LoadFromCacheOrDownload只是一个普通的new WWW
2.直接加载AssetBundle对象:
public static AssetBundle LoadFromFile(string path, uint crc = 0):新的从文件建立加载AssetBundle方法,loadFromFile方法支持上一节中提到的几个压缩格式,针对LZ压缩格式和未压缩的磁盘上的bundle文件,该方法会直接加载。针对使用默认的LZMA压缩格式压缩的bundle文件,该方法会在幕后先将bundle文件解压后再加载。这是最快的加载AssetBundle的方式。该方法是同步版本,还有异步版本:LoadFromFileAsync。
public static AssetBundle LoadFromMemory(byte[] binary, uint crc = 0):从内存中获取Bundle的二进制数据,同步地建立AssetBundle对象。该方法通常用在通过加密的数据上,通过加密的流数据通过解密以后咱们能够调用该方法动态的建立AssetBundle对象。该方法是同步版本,还有异步版本:LoadFromMemoryAsync。
3、资源加载
LoadAsset:从资源包中加载指定的资源
LoadAllAsset:加载当前资源包中全部的资源.
LoadAssetAsync:从资源包中异步加载资源
在Bundle中加载的Prefab是不能直接使用的,它须要被实例化以后,才能使用,而对于这种Prefab,实例化以后,这个Bundle就能够被释放了
GameObject obj = GameObject.Instantiate(bundle.Load("MyPrefab")) as GameObject;
bundle.Load("MyPrefab", typeof(GameObject))加载的时候最好传入资源的类型加密

4、针对项目的建议
因为以上分析的几种加载手段各有各的使用情景和特色。所以建议在咱们的项目中按照如下情景使用这些方法:
1.随游戏一同发布的AssetBundle(通常位于StreamingAssets文件夹中):在打AssetBundle包时,使用LZ4压缩格式进行打包(开启BuildAssetBundleOptions.ChunkBasedCompression便可)。
2.在运行时须要加载AssetBundle对象时,使用LoadFromFile方法进行加载。
这样作的好处是:便可以将AssetBundle文件压缩,又能够兼顾加载速度,且节约内存。
3.在打AssetBundle包时,使用默认的LZMA格式压缩。
4.使用WWW.LoadFromCacheOrDownload方法下载并缓存AssetBundle包文件。url