学习进度
0/9 已勾只保存在这台浏览器;勾满 9 项即视为本题完成。
先把题目说成人话
一个英雄看起来像一件资源,真正显示时却同时需要模型、材质、纹理和着色程序。少下载其中一件,角色就可能整身变粉。
把资源装成可下载文件的底层容器叫资源包(AssetBundle);帮助引擎(Unity)根据地址找到资源、继续找到它所依赖的其他资源,并管理加载与释放的上层系统叫可寻址资源系统(Addressables)。后者通常仍然把内容构建成这种资源包,所以两者不是互相排斥的两种压缩格式。
这是虚构教学故事,不是个人项目经历。
场景:先让问题变得看得见
游戏准备发布一张新海港地图。它由场景、英雄模型、材质、纹理和全项目共享的 Shader 组成。题干虽然提到腾讯,但没有给出某个腾讯项目的真实架构,因此这里只能讨论通用的 Unity 选型,不能替腾讯项目宣布统一答案。
(右脑)画面:玩家看到海港下载进度达到百分之百,进入以后却只看见一尊粉色英雄。身体已经到了,动作也能播放,缺少的却是和他一起工作的着色程序。小明反复运送“英雄模型”那只箱子,粉色始终没有消失。小红查看资源之间的关系,补上漏掉的着色程序箱子,角色立刻恢复。后来发布第二版时,团队没有边下载边替换,而是在旧版旁边先准备一整套新版;新版全部到齐并检查通过以后,下一次启动才改用它。只要少一件,玩家仍使用完整旧版。
(左脑)对表:AssetBundle 是资源容器;Addressables 是基于地址、内容目录(Catalog)和加载句柄管理资源定位、依赖、异步加载、缓存与释放的上层。一个资源可用所需的全部直接和间接内容叫依赖闭包(Dependency Closure)。热更新的最低安全线是旧版继续可用、新版在独立位置完整下载和校验、明确切换版本;一个 Bundle 下载成功不能代替整版成功。
小明:先形成一个完整猜测
小明直接使用 AssetBundle。他自己写代码记住英雄在哪只包里,却漏掉了共享 Shader 包。角色包哈希正确,反复下载也无法解决粉色;问题不是箱子损坏,而是项目没有完整维护“打开英雄还需要哪些箱子”的关系。
直接管理 AssetBundle 并非错误,但地址表、依赖图、下载、缓存、版本和释放都要由团队自己建设与长期维护。
小红:把猜测放回现实检查
小红给英雄一个稳定地址,例如 characters/hero。Addressables 的 Catalog 记录这个地址对应哪只 Bundle,以及还依赖材质、纹理和 Shader 的哪些 Bundle。游戏请求英雄时,系统沿着这张关系表把所需内容一起找到。
如果团队没有成熟的自建资源平台,通常优先采用 Addressables,减少重复建设地址、依赖和加载生命周期系统。如果大型项目已经有经过长期验证的内容平台,或确实需要特殊下载、加密、跨引擎和发布规则,可以直接控制 AssetBundle。区别不是谁天然性能更高,而是谁负责管理箱子。
我:用检查结果修正模型
我把热更新先收敛成一个动作:服务器保留第一版,在旁边完整上传第二版;客户端把第二版全部下载到缓存并校验,只有成功后才记录“下次启动使用第二版”。任何一步失败,当前版本仍指向第一版。
然后才补工程深度。资源按“是否一起使用、一起更新、一起释放”分组:启动必需内容随包或预下载,地图按章节分组,共享 Shader 与材质避免被重复打进多包,可选高清内容按需获取。Bundle 太大,小改动也会产生大下载;太碎则增加文件、请求和管理成本,要用 Build Layout 与真实增量数据判断。
Addressables 负责构建 Bundle/Catalog、地址解析、依赖下载、缓存和句柄生命周期,但不会自动提供完整发布事务。在它外面仍需要启动与发布层:每个内容版本使用不可变目录,一份发布清单(Release Manifest)指向 Catalog、兼容的应用版本、文件哈希和依赖集合。哈希或 CRC 用来发现损坏和确认内容身份;密码学签名才用来确认发布者。
切换应发生在 Addressables 初始化和首次资源加载以前。如果本进程已经根据新 Catalog 创建了对象,仅换回旧目录并不能让内存中的新资源自动消失;默认安全回滚放到下一次启动。运行时加载得到的句柄仍要按生命周期释放,否则离开地图后资源可能继续常驻。
(右脑)画面修正:现在只保留一条主线:英雄不是一只箱子,而是一组必须同时在场的箱子;Addressables 帮忙记住它们的关系,热更新则在旧仓库旁边先准备完整新仓库。核心画面形成以后,再回头理解分组、校验和回滚:它们分别在解决“箱子怎样摆”“有没有损坏”“切错以后怎样回去”,不再同时挤进第一幕。
(左脑)严格对表:构建时按生命周期分组,生成 Bundle、Catalog 与完整依赖集合;发布时上传到不可变版本目录,生成含 Catalog、哈希、应用兼容范围和依赖的 Release Manifest;客户端先检查磁盘并下载候选版本,再验证依赖、哈希与签名,成功后只更新“下次启动版本”指针。运行时保存并释放 Addressables 句柄;验收弱网中断、CDN 404、磁盘不足、缓存峰值、实际增量、引用释放与旧版重启恢复。UpdateCatalogs 更新资源定位关系,但不能被当成无条件的同进程原子回滚。
老师解惑
- AssetBundle:资源打包与运行时加载的底层容器;目录、依赖和发布策略仍需外部系统负责。
- Addressables:以地址和句柄管理定位、依赖、异步加载、缓存与释放,构建产物通常仍是 AssetBundle。
- 依赖闭包:英雄可用所需的全部直接和间接依赖;少一个共享 Shader 也算整次更新失败。
- 内容分组:按共同使用、更新和释放关系权衡;过大增加增量下载,过碎增加请求和管理成本。
- 版本切换:候选版本全部验证以后才改变下次启动所选版本,避免半新半旧。
- 校验与签名:哈希检查内容,签名检查发布者,两者职责不同。
- 加载句柄:资源不用以后必须按约定释放;Addressables 不会替错误生命周期设计兜底。
工具分工
- Addressables Analyze / Build Layout Report:检查重复依赖、分组和 bundle 体积。
- Catalog 与 CDN 日志:核对地址解析、版本、哈希、重试和回退原因。
- Unity Profiler / Memory Profiler:验证加载与释放后的常驻资源。
- 弱网与磁盘故障注入:证明更新能中断续传或安全失败,而不只验证理想网络。
记忆钩子
Bundle 是箱子,Addressables 是仓储系统;热更新成功的标准是整套依赖能校验、切换、回退。
这是教学场景,不是目标项目的真实捕获或个人经历。
下一步:验证这条因果
Addressables 地址、Catalog/Hash、底层 AssetBundle 依赖、缓存、激活闸门与稳定版回退怎样连成一条内容更新链。
教学边界:网页不连接 CDN、不加载真实 Bundle,也不把内容更新冒充 Player 代码热更或 Addressables 自带事务回滚。