Unity 热更新(一)

核心知识点:热更新与冷更新概念、AB 包概念与作用、AB 包属性配置、编辑器打包工具、三种压缩算法、Manifest 清单文件、CRC/MD5/SHA1 校验码、分包策略、依赖关系、AB 包卸载、多种加载方式(同步 / 异步、文件 / 内存 / 流、Manifest 逆向加载、UnityWebRequest)

一、热更新与冷更新

1 概念

冷更新 :应用商店完整重新下载安装包,替换整个 App,Android 是 APK、iOS 是 IPA。 热更新:不需要重新安装完整安装包,游戏运行时增量下载资源(模型、贴图、预制体、场景),实现资源更新;C# 编译后的脚本无法直接通过 AB 包热更(IL2CPP 编译后为机器码)。

语言区分:C#/C++ 属于编译型语言;Lua、Python、JS 属于解释型脚本语言,可以运行时解释执行,可做代码热更。

2 特性 / 规则

  1. AB 包只能承载资源 (预制体、模型、贴图、音效、场景),不能存放 C# 脚本

  2. 热更新一般流程:①设置 AB 资源标记 ②编辑器构建 AB 包 ③服务端存放 AB 包资源 ④客户端下载 ⑤客户端加载 AB 包使用资源。

4 相关知识点对比

冷更新 VS 热更新

冷更新:完整安装包,包体积大,必须应用商店审核; 热更新:只下载变更资源,增量更新,不需要重装 App;仅资源可以热更,原生 C# 脚本不行。

5 模块拓展

代码热更需要 Lua 框架(XLua、ToLua)。

二、AssetBundle(AB 包)基础概念

1 概念

Unity 专有资源压缩包,把模型、贴图、音效、预制体、场景打包成独立压缩包;支持分包、记录资源依赖关系,用于热更新,减小初始安装包体积。

2 特性 / 规则

  1. 不支持 C# 脚本,其他资源均可打包;

  2. 自带依赖记录,A 资源依赖 B 资源,会在 Manifest 记录依赖;

  3. 压缩算法:LZ4、LZMA、Uncompressed(不压缩);

  4. 可以放到服务端,游戏运行下载到本地再加载;

  5. Resources 文件夹内资源全部打进安装包,无论是否使用;AB 包资源初始不进主包,可以后续下载。

3 语法 & 编辑器配置

在 Project 窗口选中资源,Inspector 底部设置AssetBundle Name,设置包名(后缀可以自定义,商业项目一般做文件名混淆加密)。

C# 脚本没有 AB 包设置项,脚本不能打入 AB 包。

4 相关知识点对比

Resources VS AssetBundle

Resources:打包全部打入主包,运行时直接 Load,不能热更; AB 包:资源可外置服务端,按需下载加载,支持热更新、分包。

5 模块拓展

商业项目会对 AB 包文件做简单加密,防止资源被直接提取破解。

三、编辑器构建 AB 包(Editor 工具)

1 概念

编写 Editor 文件夹内菜单工具,调用 Unity API 批量构建 AB 包;打包代码必须放在 Editor 文件夹,打包工具仅编辑器可用,打包进 App 会被剔除。

2 特性 / 规则

  1. 输出路径需要代码判断,不存在就创建文件夹;

  2. 需要指定目标平台(Windows/Android/iOS),不同平台 AB 包资源格式不互通;

  3. 指定压缩模式;

  4. 构建完成会生成 AB 资源文件 + .manifest清单文件。

3 语法 & 代码片段

复制代码
using UnityEditor;
using System.IO;
public class BuildABTool{
    [MenuItem("Tools/Build AssetBundle")]
    static void BuildAllAB(){
        string outPath = "AssetBundles";
        if (!Directory.Exists(outPath))
            Directory.CreateDirectory(outPath);
        BuildAssetBundleOptions opt = BuildAssetBundleOptions.None; //有多种压缩方式,None是一种
        BuildTarget target = BuildTarget.StandaloneWindows64;
        BuildPipeline.BuildAssetBundles(outPath, opt, target);
    }
}

4 相关知识点对比

手动拷贝资源 VS AB 分包构建

全部资源打主包:安装包体积巨大,无法增量更新; AB 分包:初始主包小,资源按需下载更新。

5 模块拓展

打包前自动清理旧输出目录。

四、三种 AB 包压缩模式

1 概念

BuildAssetBundleOptions 控制压缩算法,三种模式:LZMA、LZ4、Uncompressed。

2 特性 / 规则

  1. None(LZMA):高压缩率,包最小;加载时整体解压;需要完整解压后再使用;CPU 解压开销大。

  2. ChunkBasedCompression(LZ4) :折中方案;可以按需局部解压,不需要解压整个包;项目最常用;包体积比 LZMA 大,CPU 开销低。

  3. Uncompressed:完全不压缩;体积最大;加载最快,无解压开销;仅本地测试用。

4 相关知识点对比

模式 压缩算法 包大小 加载特性 适用场景
None (默认打包格式) LZMA 最小 整体解压,CPU 开销高 网络存储,追求极小包体
ChunkBasedCompression LZ4 中等 按需局部解压,开销低 项目正式发布,首选
Uncompressed 最大 无需解压加载快 本地测试调试

5 模块拓展

压缩率越高,CPU 解压开销越大,要在包体大小和性能之间做平衡。

五、Manifest 清单文件 & 校验码 CRC/MD5/SHA1

1 概念

构建 AB 包同时生成 manifest 清单,分为总包 manifest、每个 AB 包自己的 manifest;记录包名、版本号、CRC 校验码、资源列表、依赖关系。

2 特性 / 规则

  1. Manifest 核心信息: 版本号:客户端与服务端版本对比,判断是否需要更新资源; CRC/MD5/SHA1 校验码:校验下载后文件完整性,判断传输是否损坏; 资源清单:包内部包含哪些资源; 依赖列表:记录当前 AB 包依赖哪些其他 AB 包。

  2. 校验码对比: CRC:16 位,速度快; MD5:128 位; SHA1:160 位,校验最严格。

3 语法 & 使用逻辑

客户端下载 AB 包,拿本地文件校验码与服务端 manifest 内校验码对比,不一致说明文件损坏,重新下载。

4 相关知识点对比

没有校验 VS CRC 校验

无校验:网络传输损坏的资源直接加载,会出现贴图丢失、模型异常; CRC 校验:检测文件损坏,自动重下。

5 模块拓展

热更新流程核心:对比版本号→对比校验码→下载损坏 / 新版本 AB 包。

六、AB 包分包策略与依赖

1 概念

多个资源之间存在引用依赖(模型引用贴图);如果模型和贴图分到不同 AB 包,只加载模型 AB 包而没有加载贴图 AB 包,贴图会丢失;必须把所有依赖包提前加载进内存。

2 特性 / 规则

  1. 分包常见策略 按类型分包:贴图包、模型包、音效包; 按业务模块分包:UI 包、背包资源包、战斗怪物资源包; 按场景分包:场景 A 资源包、场景 B 资源包; 按更新频率分包:经常更新的包、不经常更新的包。

  2. 分包禁忌:不能出现资源冗余,同一个资源被打进多个 AB 包,内存重复占用。

  3. manifest 可以读取 AB 包全部依赖列表,代码自动加载所有依赖包。

3 语法 & 代码片段(依赖加载逻辑伪代码)

复制代码
//读取manifest拿到某AB包所有依赖包名
string[] deps = manifest.GetAllDependencies("test.ab");
foreach(var depName in deps){
    //提前加载每一个依赖AB包
    AssetBundle.LoadFromFile(depPath);
}
//再加载主AB包
AssetBundle mainAb = AssetBundle.LoadFromFile(mainPath);
//读取资源并实例化
GameObject cubePrefab = mainAb.LoadAsset<GameObject>("Cube");
GameObject cube = Instantiate(cubePrefab);

4 相关知识点对比

全部资源一个 AB 包 VS 合理分包

单大包:更新微小资源也要下载整个大包,流量消耗大; 合理分包:只更新发生改动的小包。

5 模块拓展

分包粒度权衡:包数量太多管理复杂;包太大增量更新效率低。

七、AssetBundle 卸载 Unload

1 概念

AB 包加载进内存,不用的时候需要卸载释放内存;AssetBundle.Unload(bool unloadAllLoadedObjects)

2 特性 / 规则

  1. Unload(true)卸载该 AB 包加载出来的所有资源对象,哪怕场景中正在使用,也会被卸载,物体材质贴图丢失;

  2. Unload(false):只卸载 AB 包本身文件内存;已经实例化到场景的资源对象保留不卸载;只释放 AB 包文件内存。

  3. 长期不用的 AB 包调用 Unload 释放内存,防止内存持续上涨。

3 语法 & 代码片段

复制代码
AssetBundle ab;
ab.Unload(true);  //卸载包+所有由这个包加载出来的资源
ab.Unload(false); //仅卸载AB包文件,已使用的资源保留

4 相关知识点对比

Unload(true) VS Unload(false)

true:彻底释放,但容易造成场景资源丢失;适合完全不再使用该包所有资源; false:只释放包文件内存;场景物体不受影响;适合临时切换,资源还会复用。

5 模块拓展

Resources.UnloadUnusedAssets () 卸载场景未使用资源。

八、AB 包多种加载方式(同步 / 异步)

1 概念

AB 包提供多套加载 API,分为同步、异步;异步用协程 +AssetBundleCreateRequest,不会卡住主线程。

常用三类:LoadFromFile、LoadFromMemory、LoadFromStream;另外 Manifest 逆向加载、UnityWebRequest 网络加载。

2 特性 & 语法

① LoadFromFile(最常用,LZ4/LZ4 压缩包优先)
复制代码
//同步
AssetBundle ab = AssetBundle.LoadFromFile(path);
//异步
AssetBundleCreateRequest req = AssetBundle.LoadFromFileAsync(path);
yield return req;
AssetBundle ab = req.assetBundle;

优点:不需要把整个包读进托管内存,开销低; 限制:不支持加密 AB 包,只能明文包

② LoadFromMemory(从字节数组 byte \[\] 内存加载)
复制代码
byte[] bytes = File.ReadAllBytes(path);
AssetBundle ab = AssetBundle.LoadFromMemory(bytes);

把整个文件全部读进托管堆内存;适合加密后的包,解密得到 byte \[\] 再加载;内存开销更大。

③ LoadFromStream 文件流加载
复制代码
FileStream fs = File.Open(path,FileMode.Open,FileAccess.Read);
AssetBundle ab = AssetBundle.LoadFromStream(fs);

缓冲区流式读取,适合加密 AB 包;速度相比 File 更慢。

④ Manifest 逆向加载(先读取 manifest,再拿依赖、再加载 AB 包)

正向加载:直接 LoadFromFile 加载 AB 包; 逆向加载:先加载总包 manifest,通过 API 获取所有包名、依赖列表,再动态加载对应 AB 包;热更新项目标准写法。

⑤ UnityWebRequest(网络下载 AB 包,异步)
复制代码
using UnityEngine.Networking;
UnityWebRequest req = UnityWebRequest.GetAssetBundle(url);
yield return req.SendWebRequest();
AssetBundle ab = DownloadHandlerAssetBundle.GetContent(req);

支持 http 网络地址下载 AB 包;下载完成一般会保存到本地磁盘,下次直接 LoadFromFile 本地读取,不用重复下载。

4 相关知识点对比

同步加载 VS 异步加载

同步:会阻塞主线程,游戏卡顿;小资源可以,大资源禁止在 Update 主线程直接同步 Load; 异步协程:不会卡住游戏,正式项目优先异步加载。

5 模块拓展

下载完成后持久化保存 AB 包到本地 PersistentDataPath 目录。

综合拓展

1 AB 包完整热更新流程 设置资源 AB 标记 → Editor 工具构建 AB 包,生成 manifest、CRC 校验码 → AB 包上传 HTTP 服务端 → 客户端启动:下载 manifest,版本、CRC 对比 → 下载需要更新的 AB 包保存本地 → 异步加载 AB 包、自动加载全部依赖包 → 读取包内资源实例化使用 → 不用时调用 Unload 释放内存。

2 高频 Bug 排查清单

贴图模型丢失:分包后没有加载依赖 AB 包; AB 包打包报错:脚本放在非 Editor 文件夹,打包 API 运行时调用; 资源加载贴图消失:Unload (true) 卸载正在使用的资源; LoadFromFile 加载失败:AB 包做了加密(LoadFromFile 不支持加密,改用 Memory/Stream); 不同平台 AB 包不能混用:Windows 打包出来的 AB 包不能直接在 Android 运行。

3 核心考点 热更新 / 冷更新区别、AB 包三大压缩算法优缺点、Manifest 清单作用、CRC 校验码、分包策略、依赖关系、Unload (true/false) 区别、多种加载 API 适用场景、正向加载与 Manifest 逆向加载。

4 进阶拓展学习方向 XLua 代码热更新、AB 包加密、增量差分更新、PersistentDataPath 本地持久目录、下载进度回调。

相关推荐
软件黑马王子21 分钟前
1.non-MonoBehaviour 单例模式泛型基类
unity·前端框架·c#
KhalilRuan13 小时前
Unity性能优化
unity·性能优化·游戏引擎
ellis197013 小时前
u3d IMGUI[二] 编辑器扩展
unity
五仁烧饼1 天前
Unity性能优化系列内存篇 - 移动端内存优化
unity·性能优化·游戏引擎
WiChP2 天前
【V0.1B15】从零开始的2D游戏引擎开发之路
游戏引擎
zhchyun20084 天前
# 【Unity UI 进阶】仿 Element UI 打造企业级 Unity UI 组件库(06)
ui·unity·游戏引擎
Behaviour4 天前
Unity游戏HybridCLR 热更新接入实战
游戏·unity·游戏引擎
LONGZETECH5 天前
新能源汽车动力电池实训教学痛点与虚拟仿真技术解决方案
c语言·3d·unity·架构·汽车·汽车教学软件
王维志5 天前
UiSplineRenderer
unity·游戏引擎