AssetBundle的加载与卸载方式摘要
文中Object和Asset两个词用的比较混乱,但是Unity的官方英文文档里就是不停地在用这两个词,所以这里也没有替换为中文。
用于加载AssetBundle的API
AssetBundle.LoadFromFile[Async]()
首选方法(在速度、磁盘使用和内存占用方面都很高效)适用于从本地存储加载未压缩或LZ4压缩的AssetBundle使用LZMA压缩的AssetBundle会被解压到内存中使用LZ4压缩或未压缩的AssetBundle会直接从磁盘读取 AssetBundle.LoadFromStream[Async]()
适用于从流式数据中加载AssetBundle使用LZMA压缩的AssetBundle会被解压到内存中使用LZ4压缩或未压缩的AssetBundle会直接从流数据中读取加载过程中不能Dispose流式对象 UnityWebRequest[AssetBundle].GetAssetBundle()
适用于从远程下载AssetBundle能够缓存已下载的AssetBundle以便重用缓存系统中的AssetBundle仅以文件名进行标识而不是使用URL AssetBundle.LoadFromMemory[Async]()
不推荐使用会产生AssetBundle的冗余副本
方括号[]用来表示类或方法的其他版本,下同。
用于从AssetBundle中加载Asset的API
AssetBundle.LoadAsset[Async]()
首选方法适用于加载AssetBundle中的单个Object当要加载AssetBundle中超过66%的Object时,考虑使用LoadAllAssets()方法 AssetBundle.LoadAllAssets[Async]()
适用于一次性加载AssetBundle中的全部Object比多次调用LoadAsset()更快 AssetBundle.LoadAssetWithSubAssets[Async]()
适用于从AssetBundle中加载含有多个嵌套Object的复合Asset如果要加载的Object都来自于同一Asset并且他们和很多不相关的其他Object放在同一AssetBundle内,那么应该使用此方法
当Object被加载完成后,会调用它的Awake()方法,并在下一帧对Unity引擎可用。
用于查询AssetBundle依赖的API
AssetBundleManifest.GetAllDependencies()
返回被AssetBundle所直接和间接依赖的所有AssetBundle的名称 AssetBundleManifest.GetDirectDependencies()
返回被AssetBundle所直接依赖的AssetBundle的名称
加载AssetBundle时不能自动加载该AssetBundle所依赖的其他AssetBundle,但从AssetBundle中加载Asset时能够自动加载该Asset所依赖的其他Asset。
AssetBundle和其所依赖的AssetBundle的加载顺序并不重要,只要在从其中加载Asset时保证被依赖的AssetBundle已经加载即可。
用于卸载AssetBundle的API
AssetBundle.Unload()
卸载此AssetBundle如果参数unloadAllLoadedObjects传入false
此AssetBundle中的Asset的压缩数据文件将被卸载无法再从此AssetBundle中加载任何Object已经从此AssetBundle中加载的Object仍能正常工作 如果参数unloadAllLoadedObjects传入true
首选方式所有从此AssetBundle中加载的Object都将被销毁Scene中对这些Object的引用将会丢失 AssetBundle.UnloadAllAssetBundles()
卸载当前已加载的所有AssetBundle参数作用与AssetBundle.Unload()方法的参数相同 Resources.UnloadUnusedAssets()
卸载所有未被使用的Asset
Asset的清理会在特定时期触发,但也可以手动触发。
当从AssetBundle中加载的Object被从活动的Scene中移除时,Unity不会自动将其卸载。
卸载AssetBundle但不卸载从其中加载的Object将会破坏此AssetBundle与Object之间的链接关系。如果之后再次加载了此AssetBundle并加载同一Object,内存中就会产生新的Object副本,而不是使用未被卸载的那个Object。
最好将那些需要同时加载或者更新的Object打包到同一个AssetBundle中。
Asset分配策略
AssetBundle太少
增加运行时内存占用增加加载时间需要下载的内容更大 AssetBundle太多
增加构建时间使开发更复杂增加整体下载时间 分组Object的基本策略
根据逻辑实体分组根据Object类型分组根据同时使用的内容分组 选择AssetBundle压缩方式时需要考虑的问题
加载时间:从本地加载未压缩的AssetBundle要比加载压缩过的AssetBundle快得多构建时间:LZMA和LZ4压缩文件的速度非常慢应用大小:如果AssetBundle被附带在项目中,将它们压缩可以减小应用程序的体积内存占用:如果考虑内存占用量,请使用不压缩或者以LZ4压缩的AssetBundle下载时间:如果AssetBundle很大或者用户网络带宽有限,那可能需要压缩如果AssetBundle中的主要内容是使用紧密压缩算法进行压缩的DXT压缩纹理,那么这个AssetBundle不应该再被压缩强烈建议开发者不要在WebGL项目中使用压缩的AssetBundle
AssetBundle补丁更新
使用AssetBundle进行补丁更新只需简单的使用新AssetBundle替换已有的AssetBundle即可。如果正在使用UnityWebRequest[AssetBundle]管理应用程序的AssetBundle缓存,那么传递一个不同的version参数即可触发下载新的AssetBundle。
补丁系统需要维护两个信息列表:
含有当前已下载的AssetBundle及其版本信息的列表含有服务器上的AssetBundle及其版本信息的列表
补丁系统应该下载服务器上的AssetBundle的信息,然后与本地的AssetBundle信息进行比对,重新下载缺失的和版本信息发生变化的AssetBundle。