• QQ
  • nahooten@sina.com
  • 常州市九洲新世界花苑15-2

游戏开发

常州手机游戏开发-Unity3D 5AssetBundle使用策略

原创内容,转载请注明原文网址:http://homeqin.cn/a/wenzhangboke/jishutiandi/youxikaifa/2019/0318/415.html

常州手机游戏开发-Unity3D 5AssetBundle使用策略


1.概览

 

Unity3D 5.0版本之后的AssetBundle机制和之前的4.x版本曾经发作了很大的变化,一些曾经常用的流程曾经不再运用,以至一些老的API曾经被新的API所取代。
因而,本文的主要内容就是剖析5.X版本的AssetBundle机制(包括创立资源包、紧缩资源包、加载资源包和从资源包中加载/卸载资源等几个方面)及其关键的API运用方式并总结一些对项目的倡议(例如依据不同的情形,选择不同的包体加载计划等等)。

2.AssetBundle系统的新功用

 

本小节包括:

  • AssetBundle系统的新功用
  • 新的AssetBundle系统的优势

2.1.AssetBundle系统的新功用

 

在新的AssetBundle系统中,呈现了以下的新功用:

  • 经过Editor中的UI即可便当的为AssetBundle标志资源。而且一个资源和对应的AssetBundle的映射将会在资源数据库(AssetDatabase)中被创立。
    在箭头处即可指定该资源所述的AssetBundle,第一个选项为AssetBundle的名字,然后一个选项则是为AssetBundle创立变体,例如一些素材需求辨别为高清或普通寄存在不同的AssetBundle中,那么第二选项就能够以hd和normal来辨别。
  • 提供了新的API用来设置资源所属的AssetBundle:
  • 设置AssetImporter.assetBundleName的值,即可为该资源指定它所属的AssetBundle。上文中在UI中设置的AssetBundle的名字便是为该值赋值,在资源有了assetBundleName之后,实践上它的信息就曾经存在于AssetDataBase里面了。
  • 新版本中,创立AssetBundle文件的API变得非常简单了:
  • BuildPipeline.BuildAssetBundles():我们只需求提供一个输出AssetBundle的地址即可。引擎将自动依据资源的assetbundleName属性(即在上文中UI中设置的值)批量打包,自动树立Bundle以及资源之间的依赖关系。
  • 新增了一些打包战略/选项,且一些4.x中的旧有战略被默许开启。
  • CompleteAssets ,用于保证资源的完备性,默许开启;
  • CollectDependencies,用于搜集资源的依赖项,默许开启;
  • DeterministicAssetBundle,用于为资源维护固定ID,默许开启;
  • ForceRebuildAssetBundle,用于强迫重打一切AssetBundle文件,新增;
  • IgnoreTypeTreeChanges,用于判别AssetBundle更新时,能否疏忽TypeTree的变化,新增;
  • AppendHashToAssetBundleName,用于将Hash值添加在AssetBundle文件名之后,开启这个选项能够直接经过文件名来判别哪些Bundle的内容停止了更新(4.x下普遍需求经过比拟二进制等办法来判别,但在某些状况下即便内容不变重新打包,Bundle的二进制也会变化),新增。
  • ChunkBasedCompression,用于运用LZ4格式停止紧缩,5.3新增。
  • Manifest文件。在4.x版本中,我们通常需求自行维护配置文件,以记载AssetBundle之间的依赖关系,并供运转时运用。而在5.x版本中,运用Manifest文件能够免去4.x版本中的这一过程。而Manifest文件分为两种:
  • 单个bundle的Manifest文件,一旦一个新的AssetBundle文件被创立导出,便会对应生成一个.manifest文件,其中包含了校验、依赖文件等信息。所以能够用来做增量更新。
  • 实践上在打包的时分,在输出的bundle所在的文件夹内还会生成一个总的manifest文件,叫做[文件夹名].manifest。它包含了该文件夹内一切的bundle的信息,以及它们之间相互依赖的信息。所以在我们加载bundle的时分,需求先把总的manifest文件加载进来,以确认各个bundle之间的依赖关系。
  • 一些在运转时动态加载AssetBundle的API被新的API替代。
  • 4.x版本中的AssetBundle.CreateFromFile办法,在5.x版本中变成了AssetBundle.LoadFromFile办法。
  • 4.x版本中的AssetBundle.CreateFromMemory办法,在5.x版本中变成了LoadFromMemoryAsync办法。
  • 4.x版本中的AssetBundle.CreateFromMemoryImmediate办法,在5.x版本中变成了LoadFromMemory办法。

2.2.新的AssetBundle系统的优势

 

由于引擎提供的这些新功用,我们就不再需求像4.x时期那么复杂的用来打包的脚本了。
同时,资源之间的相互依赖关系不再需求开发者手动维护了,曾经由于不当运用PushAssetDependencies/PopAssetDependencies而可能会形成依赖呈现的问题,如今Unity3D曾经为我们处理了。
而且由于引入了清单文件manifest,因而我们能够完成增量更新,即只需求更新有变化的局部,而没有变化的则不用更新。
举一个例子:
假定我们有一个cube,它的material有一个材质,我们分别将cube和material打包成cubeBundle和materialBundle,之后我们修正material上的材质。在过去,我们需求分别重新为cube和material打包,而如今只需求对material重新打包即可,cube不受影响。

3.AssetBundle文件的创立

 

本小节包括:

  • 旧有创立AssetBundle文件的API
  • 新的创立AssetBundle文件的API
  • 针对项目的倡议

3.1.旧有创立AssetBundle文件的API

 

在4.x时期,最常用的AssetBundle打包办法主要包括以下两个:

  • BuildPipeline.BuildAssetBundle
    对除Scene以外的资源打包,支持单个和多个资源,需求在办法的参数中指明需求被打入AssetBundle的资源;
  • BuildPipeline.BuildStreamedSceneAssetBundle
    对Scene文件打包,也支持单个和多个。

且在4.x时期,打包还需求留意资源之间相互依赖的问题。为了防止资源冗余,同时进步资源加载和卸载的灵敏性,因而依赖性打包的重要性显而易见。老版本中,我们能够运用以下两个办法来完成这种依赖性:

  • BuildPipeline.PushAssetDependencies
  • BuildPipeline.PopAssetDependencies

这种机制并不难了解,简单的说PushAssetDependencies是将资源进栈,PopAssetDependencies是让资源出栈,每打一个包,引擎都会检查当前栈中一切的依赖项,查看能否有相同资源曾经在栈中。如有,则与其相关的AssetBundle树立依赖关系。

3.2.新的创立AssetBundle文件的API

 

在新版本中,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办法即可:


  1.  
    using UnityEditor;
  2.  
     
  3.  
    public class CreateAssetBundles
  4.  
    {
  5.  
    [MenuItem ("Assets/Build AssetBundles")]
  6.  
    static void BuildAllAssetBundles ()
  7.  
    {
  8.  
    BuildPipeline.BuildAssetBundles ("Assets/AssetBundles");
  9.  
    }
  10.  
    }

BuildPipeline.BuildAssetBundles办法的参数为bundle的导出目录。当然它有很多重载的版本,能够提供额外的参数来定制契合本人需求的AssetBundle。

3.3.针对项目的倡议

 

固然新的AssetBundle简化了打包和处置资源依赖的过程,但是却引入了一个新的复杂度,即需求设置资源的assetbundleName以完成打包的功用。 因而我们可能需求做的是:

  1. 提供脚本批量对资源设置assetbundleName
  2. 规划好assetBundle所对应的资源类型,规划好assetBundle的数量

4.AssetBundle的紧缩

 

本小节包括:

  • AssetBundle的紧缩类型
  • 针对项目的倡议

4.1.AssetBundle的紧缩类型

 

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即可。


  1.  
    BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath,
  2.  
    BuildAssetBundleOptions.ChunkBasedCompression);

不紧缩: 当然,我们也能够不对AssetBundle停止紧缩。没有经过紧缩的包体积最大,但是访问速度最快。 若要运用不紧缩的战略,只需求在打包的时分开启BuildAssetBundleOptions.UncompressedAssetBundle即可。


  1.  
    BuildPipeline.BuildAssetBundles(Application.streamingAssetsPath,
  2.  
    BuildAssetBundleOptions.UncompressedAssetBundle);

4.2.针对项目的倡议

 

AssetBundle的紧缩战略不只仅和包体的大小、包体的解压速度相关,而且还会关系到AssetBundle在运转时动态加载的API运用。因而,针对不同类型资源的AssetBundle要指定出契合其运用特性的紧缩战略。

5.AssetBundle的加载和卸载

 

本小节主要包括:

  • 新版API
  • 动态加载方式比照
  • 针对项目的倡议

5.1 新版API

 

在5.x版本中的新AssetBundle系统中,旧有的一些动态加载API曾经被新的API所取代,详细内容如下:

  • 4.x版本中的AssetBundle.CreateFromFile办法,在5.x版本中变成了AssetBundle.LoadFromFile办法。
  • 4.x版本中的AssetBundle.CreateFromMemory办法,在5.x版本中变成了LoadFromMemoryAsync办法。
  • 4.x版本中的AssetBundle.CreateFromMemoryImmediate办法,在5.x版本中变成了LoadFromMemory办法。

因而,本小节之后的内容将运用新版API。

5.2.动态加载方式比照

 

运用AssetBundle动态加载资源首先要获取AssetBundle对象,第二步才是从AssetBundle中加载目的资源。因而本小节将主要关注如何在运转时获取AssetBundle的对象,关于如何从AssetBundle中加载资源将在下一小节中剖析。 要在运转时加载AssetBundle对象主要能够分为两大类途径:

  • 先获取WWW对象,再经过WWW.assetBundle获取AssetBundle对象
  • 直接获取AssetBundle

下面我们就详细剖析一下这两种途径:

先获取WWW对象,再经过WWW.assetBundle加载AssetBundle对象: 在先获取WWW对象,在获取AssetBundle的这种方式中,我们能够运用以下两个API来完成这个功用。

  • 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从磁盘中的缓存获取。

直接加载AssetBundle对象: 在4.x时期,我们能够经过CreateFromFile或CreateFromMemory办法将磁盘上的文件或内存中的流结构成我们需求的AssetBundle对象。但是在5.x版本中,曾经的这两个办法曾经被新的LoadFromFile、LoadFromMemory办法所替代(这两个办法还有异步的版本),且机制上也有了一些区别。

  • public static AssetBundle LoadFromFile(string path, uint crc = 0):新的从文件创立加载AssetBundle办法和4.x中的CreateFromFile办法在机制上有了一些分别,旧的CreateFromFile必需运用未紧缩的Bundle文件才干在运转时动态创立AssetBundle对象。而新的LoadFromFile办法则没有这个请求,它支持上一节中提到的几个紧缩格式,针对LZ紧缩格式和未紧缩的磁盘上的bundle文件,该办法会直接加载。针对运用默许的LZMA紧缩格式紧缩的bundle文件,该办法会在幕后先将bundle文件解压后再加载。这是最快的加载AssetBundle的方式。该办法是同步版本,还有异步版本:LoadFromFileAsync。
  • public static AssetBundle LoadFromMemory(byte[] binary, uint crc = 0):从内存中获取Bundle的二进制数据,同步地创立AssetBundle对象。该办法普通用在经过加密的数据上,经过加密的流数据经过解密之后我们能够调用该办法动态的创立AssetBundle对象。该办法是同步版本,还有异步版本:LoadFromMemoryAsync。

以上便是在运转时动态加载AssetBundle对象的办法。下面,我们再从加载过程中内存耗费的角度来比照一下这几种加载AssetBundle对象的办法,下表是Unity3D官方的一个中文版总结。 留意:当运用WWW来下载一个bundle时,WebRequest还会有一个8*64KB的缓存区用来存储来自socket的数据。

5.3.针对项目的倡议

 

由于以上剖析的几种加载手腕各有各的运用情形和特性。因而倡议在我们的项目中依照以下情形运用这些办法:

  • 随游戏一同发布的AssetBundle(普通位于StreamingAssets文件夹中):
  • 在打AssetBundle包时,运用LZ4紧缩格式停止打包(开启BuildAssetBundleOptions.ChunkBasedCompression即可)。
  • 在运转时需求加载AssetBundle对象时,运用LoadFromFile办法停止加载。
  • 这样做的益处是:即能够将AssetBundle文件紧缩,又能够统筹加载速度,且节约内存。
  • 作为更新包,需求从效劳端下载的AssetBundle:
  • 在打AssetBundle包时,运用默许的LZMA格式紧缩。
  • 运用WWW.LoadFromCacheOrDownload办法下载并缓存AssetBundle包文件。
  • 这样做的益处是:取得了最大的紧缩率,在下载过程中能够减少数据传输量。同时,在本地磁盘创立缓存之后,又能够统筹之后的加载速度,且节约内存。
  • 我们本人停止加密的AssetBundle:
  • 在打AssetBundle包时,运用LZ4紧缩格式停止打包(开启BuildAssetBundleOptions.ChunkBasedCompression即可)。
  • 在运转时需求加载AssetBundle对象时,运用LoadFromMemory办法停止加载。(这也是从内存中运用流数据加载AssetBundle对象的仅有的运用场景。)
  • 我们本人紧缩的AssetBundle:
  • 我们本人也能够运用第三方库或工具对生成的AssetBundle包文件停止紧缩,假如需求这样做,则我们最好不要再运用Unity3D对AssetBundle停止紧缩,因而在打包时选择开启BuildAssetBundleOptions.UncompressedAssetBundle。
  • 在运转时需求加载AssetBundle对象时,运用LoadFromFileAsync办法停止异步加载。

6.资源的加载和卸载

 

本小节包括:

  • 从AssetBundle对象中加载资源
  • 资源的卸载

6.1.从AssetBundle对象中加载资源

 

新旧版的加载和卸载资源的API称号发作了一些变化,但是机制变化不大。 在旧有的4.X版本中,从AssetBundle对象中加载资源所运用的API主要包括以下几个:

  • Load:从资源包中加载指定的资源
  • LoadAll:加载当前资源包中一切的资源
  • LoadAsync:从资源包中异步加载资源

而在新版的AssetBundle中,加载资源的API曾经变成了以下的几个:

  • LoadAsset:从资源包中加载指定的资源
  • LoadAllAsset:加载当前资源包中一切的资源
  • LoadAssetAsync:从资源包中异步加载资源

6.2.资源卸载

 

资源卸载局部的变化不大,运用的依然是Unload办法。

  • Unload

该办法会卸载运转时内存中包含在bundle中的一切资源。 当传入的参数为true,则不只仅内存中的AssetBundle对象包含的资源会被销毁。依据这些资源实例化而来的游戏内的对象也会销毁。 当传入的参数为false,则仅仅销毁内存中的AssetBundle对象包含的资源。


上篇:上一篇:常州手游开发-你应该晓得的AssetBundle机制
下篇:下一篇:常州手游设计-U3D模糊效果