# 前言
前两天公司其他同事在推荐让试一试 WXAssetBundle,看看性能是不是真的有所提升,然后顺便就看到微信官方推荐使用 Addressables 系统进行资源加载 (其实之前就有瞄到这文档,只是当时项目重点不在这,所以没怎么注意)
当然微信虽然推荐 Addressables ,也提到如果自己进行维护管理的 AB 包 性能肯定会比 AA (Addressables) 包更好 ——
AA 包较大项目时生成的未压缩的 catalog 较大,加载效率低
所以微信推荐的原因是:
- 学习使用曲线平滑,便于使用和维护,并且能快速切换想要的资源管理技术。
因此,就算我们还是在使用自己的包管理方式,先了解一下总无坏处:比如上面提到的 catalog,catalog 在 Addressables 中用来干什么的?
# 总览
Addressables 底层使用引用计数维护资源关系 (这是当然,我们自己的也是),被引用自动加载时,Unity 自动维护其引用计数。不过当我们显式加载可寻址资源时,就必须在使用完该资源后释放该资源了。
- 另外,资源使用的内存只有在其所属的 AssetBundle 也被卸载后才会被释放 (与我们自己维护的一样)
所以,避免资源内存泄露的情况与使用自己的资源管理器是一样的:显式加载了记得释放。
另外需要注意:
- 如果将 Resources 文件夹中的资源设置为可寻址,则 Unity 会将资源移出目录。可以选择自己将资源移动到项目中的其他文件夹,但不能将可寻址资源存储在 Resources 目录中。
注:Windows 的文件路径限制为 260 个字符
# 加载与卸载
自动加载依赖及引用计数
主要有以下几种方式:
- AssetReferences
- 一种资源引用,可以看做 可用于替换在 MonoBehaviour、ScriptableObject 定义的常规拖上去而使用的引用资源,例如对应 GameObject:AssetReferenceGameObject 或 AssetReferenceTexture 等,而 AssetReference 可认为是对应此前 Object 类型 (可以拖任何对象上去)
- 此外,也可以使用 AssetReferenceUILabelRestriction 限制能拖上去指定标签的 Addressables 对象
- 注:AssetReference.cs 中有详细列表
- 通过地址 (路径) 加载
Addressables.InstantiateAsync(path)
Addressables.LoadAssetAsync<GameObject>(path)
- 通过标签加载
- IResourceLocation
与常规资源一样,加载之后需要对应卸载资源。
注:加载时也可以采用 async、await 异步方法,其 Load 方法中有 Task
属性
# 分组和标签
- 分组用于组织具体内容,每个组可以有自己的打包设置 (如整个组单打为一个包,或分离打包、名字是否带 Hash 等)
- 一个组打包成一个 Bundle
- 组内每个资源都单独打成一个 Bundle
- 组内同一标签的打成一个 Bundle
- 同时也可以支持通过标签加载 (如果设置了标签的话)
# 资源清单 (catalogs)
即 catalogs 文件,Addressables 用来管理资源加载、依赖啥的
catalog_{日期}.hash
- 检查 catalog.json 文件是否发生变化
- 先下载这个,再决定是否下载 catalog_{日期}.json 文件
catalog_{日期}.json
- 具体记录依赖关系啥的数据,Bundle 越多,该文件越大
- 可以在 AddressableAssetSettings 中设置命名方式
可以自动加载,也可以手动加载,建议当然是手动加载比较好。Addressables 同样会缓存改文件,在 hash 发生变化时才会重新下载。
- 哈希文件需要与目录位于同一位置并且具有相同的名称,路径的唯一区别是扩展名。
# 手动加载方式
- Addressables.LoadContentCatalogAsync
- 可选参数是否自动释放句柄,官方建议直接传 true 自动释放
- 还可以手动调用 Addressables.CheckForCatalogUpdates 更新 (官方文档表示可以同时加载多个)
# catalogs 大小优化方式
- 压缩:打包进 AssetBundle,当然这样做会导致加载时间增加 (有提供选项)
- 注:只影响本地的 catalog,即与整包打包到 SteamingAssets 目录的那个
- 禁止包含额外资源:每个分组设置上的 IncludeXXXXX
- 这个选项得看情况设置,最新 Content catalogs 1.21.14 提供了 Disable built-in scenes and Resources 选项(我自己测试版本是 1.19 ,没这个选项,只有一些 IncludeXXXXX)
Manage catalogs at runtime | Addressables | 1.21.14
# 资源组类型
这里主要是指 『动态资源』、『静态资源』之分,其区别如下:
静态资源
Content Update Restriction 设置为 Cannot Change Post Release
动态资源
Content Update Restriction 设置为 Can Change Post Release
同时,基于是否设置为 Remote 而确定属于: 本地静态资源
、 远程静态资源
还是 远程动态资源
三类中的一类。
注:在进行完整构建之后,如果只是更新打包不要修改该项,否则对更新会有影响
# 静态资源组
分为 本地静态资源
、 远程静态资源
在资源发生变更后,可以通过菜单的 Tools->Check for Content Updates
将其自动设置到一个名为 ContentUpdate
的新分组中:
然后再使用 Build->Update Preview Build 就可以打出新组的包。
也就是说,更新打包时, Check for Content Updates
用于单独把修改过的资源挪到 UpdateContent
分组进行打包,这个分组默认设置就是 远程动态资源组
注:经测试,每次执行
Check for Content Updates
都会生成一个新的UpdateContent
远程动态资源分组,分组重名则在后面加序号。
# 本地静态资源
即 Build&LoadPaths
设置为 Local
模式
在项目构建的时候 Addressables 会自动把资源拷贝到 SteamingAssets。
- 试了下是真的 (PC 包)—— 另外 Remote (远程资源) 就不会跟随 Unity 打包进 SteamingAssets 目录。
- 简单来说,似乎就是
Library\com.unity.addressables\aa
下的会跟随打包拷入 SteamingAssets 目录。- 注: 因为
Remote资源
是在ServerData
目录,这个目录是没有的
- 注: 因为
# 远程静态资源
即 Build&LoadPaths
设置为 Remote
模式
远程静态资源一样会被复制到 ServerData
目录,这种就被称为 远程静态资源
。
- 不过远程资源肯定都是没有就去下载,所以,暂时没弄明白
远程静态资源
和远程动态资源
相比,除了更新时会单独把修改过的资源挪到UpdateContent
分组外,还有其它啥明显的区别和作用? - 感觉远程静态资源只会增加复杂性,所以还有其它在下没想到的设计考虑吗?
如上图所示,远程静态资源 (动态资源也一样) 包括其下载路径都会直接存储到本地的 catalog
数据中。
# 动态资源组
动态资源组只存在 远程动态资源
(都动态了肯定是远程下载了对吧?)
发生变更的资源会重新打包,同时直接覆盖掉原资源 (如果是附加了 Hash,则与原资源同级新增)。
如果想要进行资源更新,必须使用 Remote catalog
,即 远程动态资源组
,上述静态资源组更新而自动创建的 UpdateContent
分组即为 Remote
动态资源组。
注:远程动态资源组确实很适合微信这种按需延迟下载使用的方式,使用流程跟正常的操作几乎一样方便。
# 测试
编辑器中提供了三种加载方式:
- Use Asset Database:使用 AssetDatabase 进行加载,不用打 AssetBundle 即可测试
- Simulate Groups:模拟 AssetBundle 信息进行加载,不用打 AssetBundle 即可测试,相比第一种方式会有更多一些信息
- Use Exising Build:需要打包后加载,加载真实 AssetBundle 包
同时也直接提供了一个 Hosting
编辑器界面可用于本地打包后,开启一个模拟服务器测试远程加载资源情况,局域网内的设备也可以通过本地网络连测试资源的加载。
# EventViwer
需要勾选设置项的 Send Profiler Events
这个界面初步看来,可以查看加载的 AssetBundle 对象及其依赖啥的。其它功能还待了解。
# Analyze
资源分析界面,可用来查找重复资源引用之类的,可以方便地将重复资源直接设置到一个新分组。
# 注意
- addressables_content_state.bin
- 更新打包时需要用来对比 (Update Preview Build)
- Update Restrictions
- 区分静态资源和动态资源
- 打包之后不要变更
# 总结
过了一番流程之后,感觉官方的 Addressables 的使用确实已经比较方便,特别是连模拟加载及自带服务器模拟都提供了。
至于最开始前言提到的 "catalog" 作用,也知道了这该是属于 Addressables 的清单文件,记录了资源依赖之类的关系,必须首先加载才能进入后续流程。
当年 (记得好像是 2017 年?) 就听说官方要出新的资源管理方式,就不想去研究 AssetBundle,结果最后还是搞起了 AssetBundle,直到现在才过了一遍官方这个新的 Addressables... 如果以后我自己搞新项目,一定得实际尝试一番。
注:Addressables 是开源的。
# 参考文档
Design/UsingAddressable.md · Ocean/minigame-unity-webgl-transform - Gitee.com
Design/ResourcesLoading.md · Ocean/minigame-unity-webgl-transform - Gitee.com
Configure your project to use Addressables | Addressables | 1.21.14
Addressables 之远程内容分发
Addressables 之配置
使用 Addressable Assets System 进行资源按需加载
Unity - Addressables 项目总结(一):基础工作流