Addressables优化catalog文件
unity使用Addressables进行资源管理很方便但是有一个很值得诟病的问题, 那就是catalog文件过大, 对于一个持续运营的项目来说catalog文件可能超过10M, 导致初始化Addressables时间较长, 峰值内存上涨明显.
本文通过分析catalog文件中主要的内容占用和内存开销, 提出一些可行的(已实践)方案.
一. catalog相关的开销分析
catalog 开销主要来自两个部分:
- 初始化
Addressables的时间开销, 使用Addressables需要确保catalog加载完成, 对于部分网络情况不佳的用户造成卡顿较长的体验; - 加载
catalog文件的内存开销, 使用json格式的Addressables加载时会产生两倍于自身大小的内存开销.
加载catalog的时间开销和网络情况密切相关, 实际测试下来一个1M的catalog文件经过传输和加载到内存, 整体时间超过1s. 主要的开销来源是文件的大小.
内存上的开销主要是加载文本本身和反序列化数据之后的结果上的内存开销.
1. catalog 本身大小开销分析
catalog文件本身是一个json文件, 主要结构如下:

本身实际是ContentCatalogData的json序列化结果. 其中包含的数据是以下几类数据:
| 属性 | 数据含义 |
|---|---|
m_LocatorId |
Addressables支持多catalog,所以添加了区分不同catalog的ID |
m_InstanceProviderData |
Instantiate方法使用的Provider的序列化结果 |
m_SceneProviderData |
加载Scene使用的Provider序列化数据 |
m_ResourceProviderData |
加载资源使用的Provider的序列化结果 |
m_ProviderIds |
Provider的类名称 |
m_InternalIds |
资源的路径列表, 是AssetPath的Base64加密结果 |
m_KeyDataString |
Key的二进制序列化结果 |
m_BucketDataString |
|
m_EntryDataString |
资源的Entry的序列化结果,包含资源的类型,资源的以来等 |
m_resourceTypes |
资源的类型 |
m_InternalIdPrefixes |
InternalId列表的前缀优化数据 |
从json文件里面能看到其中比较大的主要是m_KeyDataString m_InternalIds, m_EntryDataString 分别指向了资源的路径, 资源的key和资源的加载信息其中每一段的数据的大小如下:
1 | catalog.json 16.30MB (3.20MB compressed) |
2. catalog 加载内存开销分析
// TODO
二. 可行的catalog优化方案
1.剔除locations
上面分析中发现很多的开销是来在Locations也就是资源的数量, 如果假如到catalog中的资源数量较多, 自然catalog会明显增大. 那么什么是需要添加到catalog中的什么是不需要的呢? 这里项目不一样判断的方法也不一样, 这里设计了一个简单的配置正则项去筛选需要加到Catalog中的Locations用于过滤需要保留的locations. 经过过滤之后能减少2/3的location数量, 能减少大约1/3的大小.
警告:剔除
Location可能会导致label丢失, 比如你给一个路径下的资源都标记为lableA,但是所有的资源Location被删除了导致label丢失. 使用这个方案请确保所有的通过Addressables加载的资源确实被保留了.
代码如下
1 | public class LocationFilterConfig : ScriptableObject |
2.剔除location 类型
对于同一个资源, 存在多个Entry, 其中不同的key, 不同的资源类型都会生成一个新的数据, 所以会导致同一个资源数据多很多. 这里主要是剔除key和资源类型:
2.1 剔除key
警告:剔除
key可能会导致加载资源时无法找到对应的资源而加载失败, 确保你的剔除手段是合理的
剔除key的方法很简单, 在AssetGroup里面勾选是否包含部分信息.其中分别包含的信息是是否需要使用Addresses加载资源, 是否会使用AssetReference加载资源以及是否会通过Label加载资源

2.2 剔除资源类型
对于一个资源来说, 他的资源类型有很多, 在Catalog中会生成不同类型的Entry, 比如TextAsset的资源不仅仅会存在一个TextAsset的Entry, 也会产生UnityEngine.Object资源的Entry. 这里也能按照类型剔除部分的资源类型生成的Entry.
1 | [] |
3.剔除依赖
警告:可能会导致资源加载失败, 请记得实现检查工具
依赖的数据是catalog中很大的部分, 尤其是对于依赖关系复杂的项目, 依赖的数据可能会比真实数据还多, 这里推荐使用编辑器下的资源依赖去替换使用Assetbundle计算出来的依赖关系, 减少资源的依赖数量
三.总结
Addressables是一个广泛使用的资源管理库, 使用默认的方式能确保完全不会出问题, 但是不同项目有不同的实际情况, 在做库开发时适用性应该要大于效率,但是项目实际使用的情况下应当是效率大于适用.