Appearance
Unity 资源更新管理与弱网续传下载
只更新一个头套,却要让用户重下整个安装包——这是 AssetBundle 只管压缩不管分发的必然结果。方案把资源从应用包里拆出来单独做版本管理,再配一个扛得住弱网断网的下载器。
技术问题
虚拟直播产品的虚拟形象资源以 AssetBundle 形式分发,但 AssetBundle 只是一种压缩标准,本身不带版本管理和分发下载能力。于是传统的更新路径是:全部形象资源统一打包,连同编译后的程序二进制再压缩成一个版本文件推给用户。哪怕只改了一个头套,也要走完整流程,用户重复下载未变化的资源和二进制,开发端和用户端都浪费时间、存储和带宽。
下载侧还有一个引擎级的坑:UnityWebRequest 在断网重连后下载会卡住,且不触发 timeout——弱网环境下下载任务会无声无息地吊死。
现有方案不足
- 资源与应用强绑定:所有形象资源随应用版本发布,一个小更新要全量打包、全量下载,发布链路长、包体积大。
- 无独立版本管理:资源的上下线和更新无法脱离应用发版节奏,运营侧想上下架一个形象必须等版本。
- 弱网不可恢复:引擎下载接口在断网重连场景下存在卡死缺陷,没有续传和恢复机制,弱网用户下载失败率高。
- 缓存无校验:本地缓存资源缺少一致性校验手段,可能命中损坏或非法资源。
核心思路
资源侧:拆分与独立版本管理
只把少部分形象资源打进应用包随版本发布,其余资源做独立的版本管理,在后台系统中维护更新和上下线。效果是三重的:应用包体积下降、资源更新不用发版、用户不重启应用就能拿到最新形象。
下载侧:三层架构下载器
下载器按职责分三层,层间单向取用:
mermaid
flowchart TD
A["配置层<br>提供下载所需固定参数"] --> D
B["下载层<br>封面 / 列表 / 地址 / 文件下载接口"] --> D
C["缓存层<br>缓存读写 / 一致性校验 / 下载状态"] --> D
D["下载器核心<br>初始化读配置,下载调下载层<br>校验取缓存层比对"]
D --> E["下载状态事件<br>下载中 / 成功 / 失败"]
E --> F["观察者感知实时状态"]- 配置层:初始化时提供下载所需的固定参数,例如资源地址、版本标识、缓存目录等。
- 下载层:对外提供四类接口——下载封面、下载模型文件、下载模型列表、获取下载地址;下载过程中维护缓存层的下载状态。
- 缓存层:负责缓存读写、资源一致性校验和下载状态记录。
关键机制
- 弱网续传:不依赖引擎默认行为,在设定的超时窗口内按间隔主动重新拉起连接,窗口内恢复则继续下载,超时仍未恢复才判定失败——正面绕过断网重连卡死不触发超时的引擎缺陷。
- 双端摘要比对:下载前先比服务器与本地缓存的资源摘要值,一致则直接读本地;下载后再比对落盘文件摘要,确认完整才算成功。提高缓存命中率,排除非法资源,也缓解服务器压力。
- 登录态鉴权:请求携带登录态凭证,服务器鉴权通过才下发列表和下载地址,失败即返回错误。
- 事件化状态:下载中、成功、失败三个事件对外广播,上层界面用观察者模式感知实时进度,不和下载逻辑耦合。
应用场景
- 虚拟直播 PC 端:虚拟形象资源热更新,不重启应用获取最新内容。
- 弱网环境分发:网络不稳定场景下的资源续传下载。
- 任何需要资源版本管理与分发解耦的 Unity 产品。
关联案例
- Mlive 下载器工程实践:这套三层架构与弱网续传机制在工程侧的完整落地。