Unity 热更新方案演进

ABSTRACT

从 2018 年的 AssetBundle 手动管理 + tolua/LuaFramework,梳理 Unity 热更新的两条主线——资源热更(AssetBundle → Addressables/YooAsset)与代码热更(tolua → xlua → HybridCLR)。AB「不能包含脚本」的根本限制决定了资源与代码必须双通道设计,这一架构判断至今成立。

资源热更:AssetBundle 原理(地基)

  • AB 是编辑器期创建、运行期加载的资源包,可含模型/材质/贴图/场景,不能含脚本。
  • 核心规则:整体下载缓存、不必整体加载、包内资源有依赖、按平台分别打包。
  • 依赖管理:共享资源必须显式归包,否则重复打包且丢失合批;Manifest 清单记录全部依赖。
  • 加载三阶段:AB 内存镜像 → Load 反序列化出 Asset → Instantiate(复制与引用规则不一,卸载需谨慎,防紫材)。
  • 粒度权衡:太碎管理开销大,太大带无用资源。
  • AssetBundle Manager(Unity 5 官方示例包)的 Simulation Mode 与本地资源服务器,是「免构建快速验证」思路的雏形。

代码热更第一代:tolua + LuaFramework

  • AssetBundle 热不了代码 → 引入 Lua 虚拟机,C# 通过 tolua# 与 Lua 互操作。
  • LuaFramework = PureMVC + tolua#:Lua 侧 MVC 三层(Controller/Logic/View),Wrap 文件桥接 C# API。
  • 热更链路:Lua 脚本 + AB 资源打包进 StreamingAssets → 上传 Web 服务器 → 客户端比对下载更新。
  • 经验法则:UI 与易变模块走 Lua,战斗等性能敏感模块留 C#;Lua 代码遵循 KISS。
  • 环境开关:LuaBundleMode / UpdateMode / DebugMode 三开关组合区分编辑器开发与出包。

热更工程细节补充(2016 LuaFramework 实战笔记)

  • 更新清单:服务器按「版本号/平台」目录存资源 + files.txt(文件名 + MD5 + 大小);客户端下载 files.txt?v=时间戳(防 HTTP 缓存)逐文件比 MD5,差异即下载。
  • AB 卸载用引用计数:被加载 +1、被依赖 +1,Unload 减 1,归零才真正释放——依赖共享包的卸载顺序由此决定。
  • 移动端解包:StreamingAssets 只读,首启复制到 persistentDataPath 才可增量更新;「两次解包」(先 Lua 与主界面、再全量带进度条)缩短首启等待。
  • 自举稳定性:热更界面与更新逻辑本身保持极简不变,宁可「用老的更新流程更完再说」。
  • 启动流程状态机化:Launch → Splash → CheckVersion(HotUpdate) → PreLoad → … → GameInit,断线重连回归 GameInit 重建数据(Indra 框架笔记)。
  • 出包坑:Android APK 中 StreamingAssets 默认 Store 不压缩;apktool 重打包对无后缀文件丢失该标记 → AB 变 Deflate 加载变慢。解法:AB 加后缀名 + aaptOptions.noCompress。

C# 热更的历史先声

  • 2017 年前后已有多条「不依赖 Lua」的探索:基于 IL 注入的补丁方案(C#ToIL 插桩)、CShotfix、ET 框架——路线之争最终以 HybridCLR 收敛。
  • 把全部脚本编译成 DLL 曾是代码保护手段;现代由 IL2CPP(AOT 编译为 C++)一并解决保护与性能,HybridCLR 再补回热更能力。
  • iOS 禁 JIT 是一切口热更方案的根本约束:JIT 预热消卡顿(Mono 时代)、Lua 虚拟机、HybridCLR 解释执行,都是绕开该限制的不同回答。

现代方案(2026 视角)

  • 代码热更:xlua(腾讯,Lua 方案集大成)与 HybridCLR(直接热更 C# 程序集,无脚本层割裂)已成主流;tolua/ulua 停止维护。
  • 资源热更:Addressables(官方,自动依赖与增量构建)与 YooAsset(国产商用级)取代手写 AB 管理;加载统一寻址、模拟模式、本地托管服务器等概念一脉相承。
  • 不变的原则:双通道(资源 + 代码)、统一加载接口、先编辑器模拟再真机验证、版本比对增量下发。

典型问题谱系

  • AB 按平台打包 shader → 编辑器加载移动端 AB 紫材(真机正常,用模拟模式规避)。
  • Unload(true) 时机错误 → 实例材质丢失(紫色)。
  • 加载器 DontDestroyOnLoad 保活、异步加载 + 错误兜底,古今同理。

关联概念

来源回溯