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

游戏开发

常州手游开发-你应该晓得的AssetBundle机制

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

常州手游开发-你应该晓得的AssetBundle管理机制

AssetBundle加载根底

 

经过AssetBundle加载资源,分为两步,第一步是获取AssetBundle对象,第二步是经过该对象加载需求的资源。而第一步又分为两种方式,手机App外包下文中将分离常用的API停止细致地描绘。

一、获取AssetBundle对象的常用API

 

(1)先获取WWW对象,再经过WWW.assetBundle获取AssetBundle对象:

(2) 直接获取AssetBundle:

  • public static AssetBundle CreateFromFile(string path);
    经过未紧缩的Bundle文件,同步创立AssetBundle对象,这是最快的创立方式。创立完成后只会在内存中创立较小的SerializedFile,然后续的AssetBundle.Load需求经过IO从磁盘中获取。
  • public static AssetBundleCreateRequest CreateFromMemory(byte[] binary);
    经过Bundle的二进制数据,异步创立AssetBundle对象。完成后会在内存中创立较大的WebStream。调用时,Bundle的解压是异步停止的,因而关于未紧缩的Bundle文件,该接口与CreateFromMemoryImmediate等价。
  • public static AssetBundle CreateFromMemoryImmediate(byte[] binary);
    该接口是CreateFromMemory的同步版本。
  • App开发培训注:5.3下分别改名为LoadFromFile,LoadFromMemory,LoadFromMemoryAsync并增加了LoadFromFileAsync,且机制也有一定的变化,可详见Unity官方文档。
  • public WWW(string url);
    加载Bundle文件并获取WWW对象,完成后会在内存中创立较大的WebStream(解压后的内容,通常为原Bundle文件的4~5倍大小,纹理资源比例可能更大),因而后续的AssetBundle.Load能够直接在内存中停止。
  • public static WWW LoadFromCacheOrDownload(string url, int version, uint crc = 0);
    加载Bundle文件并获取WWW对象,同时将解压方式的Bundle内容存入磁盘中作为缓存(假如该Bundle已在缓存中,则省去这一步),完成后只会在内存中创立较小的SerializedFile,然后续的AssetBundle.Load需求经过IO从磁盘中的缓存获取。
  • public AssetBundle assetBundle;
    经过之前两个接口获取WWW对象后,即可经过WWW.assetBundle获取AssetBundle对象。

二、从AssetBundle加载资源的常用API

 

  • public Object Load(string name, Type type);
    经过给定的名字和资源类型,加载资源。加载时会自动加载其依赖的资源,即Load一个Prefab时,会自动Load其援用的Texture资源。
  • public Object[] LoadAll(Type type);
    一次性加载Bundle中给定资源类型的一切资源。
  • public AssetBundleRequest LoadAsync(string name, Type type);
    该接口是Load的异步版本。
  • 常州网站开发培训注:5.x下分别改名为LoadAsset,LoadAllAssets,LoadAssetAsync,并增加了LoadAllAssetsAsync。

AssetBundle加载进阶

一、接口比照:new WWW与WWW.LoadFromCacheOrDownload

 

(1)前者的优势

  • 后续的Load操作在内存中停止,相比后者的IO操作开支更小;
  • 不构成缓存文件,然后者则需求额外的磁盘空间寄存缓存;
  • 能经过WWW.texture,WWW.bytes,WWW.audioClip等接口直接加载外部资源,然后者只能用于加载AssetBundle

(2)前者的优势

  • 每次加载都触及到解压操作,然后者在第二次加载时就省去理解压的开支;
  • 在内存中会有较大的WebStream,然后者在内存中只要通常较小的SerializedFile。(此项为普通状况,但并不绝对,关于序列化信息较多的Prefab,很可能呈现SerializedFile比WebStream更大的状况)

在管理AssetBundle时,理解其加载过程中对内存的影响意义严重。在上图中,我们常州企业培训在中间列出了AssetBundle加载资源后,内存中各类物件的散布图,在左侧则列出了每一类内存的产生所触及到的加载API:

  • WWW对象:在第一步的方式1中产生,内存开支小;
  • WebStream:在运用new WWW或CreateFromMemory时产生,内存开支通常较大;
  • SerializedFile:在第一步中两种方式都会产生,内存开支通常较小;
  • AssetBundle对象:在第一步中两种方式都会产生,内存开支小;
  • 资源(包括Prefab):在第二步中经过Load产生,依据资源类型,内存开支各有大小;
  • 场景物件(GameObject):在第二步中经过Instantiate产生,内存开支通常较小。
    在后续的章节中,我们还将针对该图中各类内存物件剖析其卸载的方式,从而防止内存残留以至泄露。

三、留意点

 

  • CreateFromFile只能适用于未紧缩的AssetBundle,而Android系统下StreamingAssets是在紧缩目录(.jar)中,因而需求先将未紧缩的AssetBundle放到SD卡中才干对其运用CreateFromFile。
    Application.streamingAsstsPath = "jar:file://" + Application.dataPath+"!/assets/";
  • iOS系统有256个开启文件的上限,因而,内存中经过CreateFromFile或WWW.LoadFromCacheOrDownload加载的AssetBundle对象也会低于该值,在较新的版本中,假如LoadFromCacheOrDownload超越上限,则常州软件技术培训会自动改为new WWW的方式加载,而较早的版本中则会加载失败。
  • CreateFromFile和WWW.LoadFromCacheOrDownload的调用会增加RersistentManager.Remapper的大小,而PersistentManager担任维护资源的耐久化存储,Remapper保管的是加载到内存的资源HeapID与源数据FileID的映射关系,它是一个Memory Pool,其行为相似Mono堆内存,只增不减,因而需求对这两个接口的运用做合理的规划。
  • 关于存在依赖关系的Bundle包,在加载时主要留意次第。举例来说,假定CanvasA在BundleA中,所依赖的AtlasB在BundleB中,为了确保资源正确援用,那么最晚创立BundleB的AssetBundle对象的时间点是在实例化CanvasA之前。即,创立BundleA的AssetBundle对象时、Load(“CanvasA”)时,BundleB的AssetBundle对象都能够不在内存中。
  • 依据经历,倡议AssetBundle文件的大小不超越1MB,由于在普遍状况下Bundle的加载时间与其大小并非呈线性关系,过大的Bundle可能惹起较大的加载开支。
  • 由于WWW对象的加载是异步的,因而逐一加载容易呈现下图中CPU闲暇的状况(选中帧处Vsync占了大局部),此时倡议恰当地同时加载多个对象,以增加CPU的运用率,同时加快加载的完成。

AssetBundle卸载

 

前文常州平台运营提到了经过AssetBundle加载资源时的内存分配状况,下面,我们分离常用的API来引见如何将已分配的内存停止卸载,最终到达清空一切相关内存的目的。

在上图中的右侧,我们列出了各种内存物件的卸载方式:

  • 场景物件(GameObject):这类物件可经过Destroy函数停止卸载;
  • 资源(包括Prefab):除了Prefab以外,资源文件能够经过三种方式来卸载:
    1) 经过Resources.UnloadAsset卸载指定的资源,CPU开支小;
    2)经过Resources.UnloadUnusedAssets一次性卸载一切未被援用的资源,CPU开支大;
    3)经过AssetBundle.Unload(true)在卸载AssetBundle对象时,将加载出来的资源一同卸载。
    而关于Prefab,目前仅能经过DestroyImmediate来卸载,且卸载后,必需重新加载AssetBundle才干重新加载该Prefab。由于内存开支较小,通常不倡议停止针对性地卸载。
  • WWW对象:调用对象的Dispose函数或将其置为null即可;
  • WebStream:在卸载WWW对象以及对应的AssetBundle对象后,这局部内存即会被引擎自动卸载;
  • SerializedFile:卸载AssetBundle后,这局部内存会被引擎自动卸载;
  • AssetBundle对象:AssetBundle的卸载有两种方式:
    1)经过AssetBundle.Unload(false),卸载AssetBundle对象时保存内存中已加载的资源;
    2)经过AssetBundle.Unload(true),卸载AssetBundle对象时卸载内存中已加载的资源,由于该办法容易惹起资源援用丧失,因而并不倡议经常运用;

二、留意点

 

在常州微信公众平台经过AssetBundle.Unload(false)卸载AssetBundle对象后,假如重新创立该对象并加载之前加载过的资源到内存时,会呈现冗余,即两份相同的资源。
被脚本的静态变量援用的资源,在调用Resources.UnloadUnusedAssets时,并不会被卸载,在Profiler中可以看到其援用状况。

UWA引荐计划

 

经过以上的解说,置信您对AssetBundle的加载和卸载曾经有了明白的理解。下面,我们将简单地做一下API选择上的引荐:

  • 关于需求常驻内存的Bundle文件来说,优先思索减小内存占用,因而关于寄存非Prefab资源(特别是纹理)的Bundle文件,能够思索运用WWW.LoadFromCacheOrDownload或AssetBundle.CreateFromFile加载,从而防止WebStream常驻内存;而关于寄存较多Prefab资源的Bundle,则思索运用new WWW加载,由于这类Bundle用WWW.LoadFromCacheOrDownload加载时产生的SerializedFile可能会比new WWW产生的WebStream更大。
  • 关于加载完后即卸载的Bundle文件,则分两种状况:优先思索速度(加载场景时)和优先思索流利度(游戏停止时)。
    1)加载场景的状况下,需求留意的是防止WWW对象的逐一加载招致的CPU闲暇,能够思索运用加载速度较快的WWW.LoadFromCacheOrDownload或AssetBundle.CreateFromFile,但需求防止后续大量地停止Load资源的操作,惹起IO开支(能够尝试直接LoadAll)。
    2) 游戏停止的状况下,则需求防止运用同步操作惹起卡顿,因而能够思索运用new WWW配合AssetBundle.LoadAsync来停止平滑的资源加载,但需求留意的是,关于Shader、较大的Texture等资源,其初始化操作通常很耗时,容易惹起卡顿,因而倡议将这类资源在加载场景时停止预加载。
  • 只在Bundle需求加密的状况下,思索运用CreateFromMemory,由于该接口加载速度较慢。
  • 尽量防止在游戏停止中调用Resources.UnloadUnusedAssets(),由于该接口开支较大,容易惹起卡顿,可尝试运用Resources.Unload(obj)来逐一停止卸载,以保证游戏的流利度。

需求阐明的是,以上常州微信小程序开发内存管理较合适于Unity 5.3之前的版本。Unity引擎在5.3中对AssetBundle的内存占用停止一定的调整,目前我们也在进一步的学习和研讨中。

以上即为我们这次为您带来的AssetBundle管理机制,希望对您的项目研发有所协助。我们会在后续技术文章经过大量的案例来进一步解释AssetBundle的管理机制,敬请关注。

 

上篇:上一篇:常州手游开发-AS导出jar包并在U3d中使用
下篇:下一篇:常州手机游戏开发-Unity3D 5AssetBundle使用策略