1、从 SBP 到 Addressables:两种不同的升级路径
前两篇文章,我们聊了 AssetBundle 的底层接口演进:第 0 代(手工收集+不处理依赖)→ 第 1 代(标记包名 或 AssetBundleBuild[] 代码定义分包,自动依赖)→ SBP(精确增量构建,源码开放)。
SBP 是一条改动最小的升级路径——你只要换了底层打包接口,增量缓存立马生效。但 SBP 不管资源「怎么管理、怎么加载」。
这时候,如果你问:「能不能连资源加载也一起简化?」答案就是 Addressables。
不过必须提前说清楚——Addressables 和 SBP 不同。SBP 是「换个打包引擎,其他一切照旧」。Addressables 是「重新定义你怎么引用资源、怎么加载资源、怎么更新资源」——这是一个改动大得多的升级。
2、Addressables 解决了哪些 SBP 没解决的问题?
SBP 解决了「打包慢」,但没解决以下问题:
- 加载代码冗长:每次加载资源都要写
AssetBundle.LoadFromFile+LoadAsset,样板代码一堆 - 依赖顺序:你得自己解析 Manifest,确保加载 Bundle A 之前把 Bundle B(A 的依赖)先加载好
- 资源定位:你得知道 Boss 这个资源在
characters.bundle里,而characters.bundle又在StreamingAssets/Bundles/characters路径下 - 热更新流程:你得一整套逻辑来下载新 Bundle、替换旧 Bundle、清理缓存、版本管理
这些都不是 SBP 的职责范围——SBP 只负责让打包更快。
Addressables 要解决的,是这整个「运行时资源管理」层面的问题。
3、Addressables 的核心思想:用”地址”代替”路径”
Addressables 里,加载资源变成了这样:
// 你不需要知道资源在哪个 Bundle、哪个路径
GameObject boss = await Addressables.LoadAssetAsync<GameObject>("Boss").Task;
对比 AssetBundle 时代的加载方式:
// 你得知道路径、知道 Bundle 名字、手动加载 Bundle 再加载 Asset
AssetBundle bundle = AssetBundle.LoadFromFile(
Path.Combine(Application.streamingAssetsPath, "characters"));
GameObject boss = bundle.LoadAsset<GameObject>("Boss");
「地址」本质上就是一个字符串 key。它可以是资源名称、文件路径、自定义标签……Addressables 在内部维护了一张映射表(Catalog),帮你从「地址」查到「这个资源在哪个 Bundle、这个 Bundle 在 CDN 的哪个路径」。
你说「我要 Boss」,Addressables 去搞定一切——加载 Bundle、处理依赖、返回资源。你不用关心它在哪个包、依赖了什么。
4、Addressables 的分组与构建
Addressables 里,资源不是直接绑定到 AssetBundle,而是先放在一个叫「Group」的逻辑分组里。一个 Group 最终会生成一个或多个 AssetBundle。
Group 比 AssetBundle 的原始名称好用得多,因为你在 Group 层面就能配置:
- 打包策略:Group 内的资源是打成一个包?还是各打各的?
- 更新策略:这个 Group 能不能热更新?CDN 地址是啥?
- 加载策略:随安装包下发?还是远程按需下载?
常见分组:
- Remote Group:放需要热更新的资源(角色模型、UI 贴图、音频),远程包放 CDN
- Local Group:放不需要更新但必须随包走的资源(基础 Shader、核心框架预制体)
并且,Addressables 的分组配置存在独立的 .asset 配置文件里,不写 .meta。这解决了第 1 代 AssetBundle 「meta 文件到处冲突」的协作痛点。
5、Addressables 底层:AssetBundle + SBP
不管 Addressables 的表面多么光鲜,底层依然是 AssetBundle。
它的工作方式:
- 你把资源拖进 Addressables Group
- 构建时,Addressables 根据 Group 配置生成打包计划
- 调用打包接口生成
.bundle文件——这里可以用BuildAssetBundles,也可以配成用 SBP - 生成 Catalog 文件(资源地址 → Bundle 位置 → CDN 路径的映射表)
- 运行时,
LoadAssetAsync("Boss")→ 查 Catalog → 找到 Bundle → 加载 Bundle → 返回资源
所以 Addressables 和 SBP 的关系是:Addressables 管「什么资源怎么管理」,SBP 管「怎么高效地把这些资源打成 Bundle」。两者互补,可以叠加使用。
6、Addressables 为什么改动大?
回到开篇的观点——Addressables 比 SBP 改动大得多,因为:
它改变了你引用资源的方式。
在传统 AssetBundle 体系里,游戏代码里引用一个资源,用的是直接引用(prefab 引用贴图,scene 引用 prefab)。Unity 在构建时通过分析这些直接引用,决定资源归属。
但在 Addressables 里,资源引用变成了「地址字符串」。GetComponent 变成了 LoadAssetAsync(“key”)。这意味着:
- 你所有加载资源的代码都要改
- 加载变成了异步操作——原来同步拿到的数据现在要等回调
- 资源生命周期管理(什么时候 Load、什么时候 Release)需要重新梳理
它改变了热更新的流程。
传统方式下,热更新是你自己设计的——版本号怎么管理、哪些 Bundle 要更新、下载失败怎么回退……每个人的设计都不一样。
Addressables 提供了一套标准化的热更新流程:Catalog 版本比对 → Diff 计算变化 Bundle → 下载 → 缓存。但这套流程是 opinionated 的——你得按它的方式来。如果你的老项目已经有一套成熟的热更新方案,迁移成本不低。
它改变了资源分组的思维。
传统方式里,你关心的是「这些资源打成几个包、每个包叫什么」。Addressables 里,你关心的是「哪些资源属于同一个 Group、这个 Group 在哪个 CDN 上」。管理的粒度从「包」变成了「组和地址」,对项目结构的理解方式都变了。
7、新的三代演进总结
加上 SBP 之后,Unity 资源打包体系的演进全景更新如下:
| 阶段 | 方式 | 核心特点 |
|---|---|---|
| 第 0 代 | BuildAssetBundle(无 s) |
手动收集资源,不处理依赖,已废弃 |
| 第 1 代 | 标记包名 / AssetBundleBuild[] + BuildAssetBundles(有 s) |
自动追踪依赖(标记模式),纯代码不分 .meta(代码模式),至今主流 |
| 第 2 代底层 | SBP | 精确增量构建,缓存大幅提升,迁移成本极低 |
| 第 2 代上层 | Addressables | 地址化加载,标准化热更新,但改动大 |
SBP 和 Addressables 同属第 2 代,但一个走底层、一个走上层,解决的是不同的问题。SBP 让打包变快,Addressables 让加载变简单。两个一起用,才是 Unity 推荐的最终状态。
下一篇,我们聊一个更底层的话题——IL2CPP。为什么 Unity 要把 C# 代码转成 C++ 再编译?Mono 和 IL2CPP 到底有什么区别?跨平台中会遇到哪些坑?
每天前进一小步,就是一个新的高度!