如何增量Patch贴图Mipmap

解读

国内上线游戏迭代节奏极快,动辄周更、双周更,而包体大小直接决定渠道分发成本与玩家转化率。贴图往往占包体50%以上,全量替换浪费流量与CDN费用,因此面试官想确认两点:

  1. 是否理解Unity贴图Mipmap链在磁盘与内存中的存储方式;
  2. 能否设计一套可灰度、可回滚、可断点续传的增量Patch管线,把“只换有差异的Mipmap层级”落地到iOS/Android原生包、小游戏分包及AssetBundle热更场景。

知识点

  1. Mipmap链数据结构:Unity将0级原图向下采样生成1~n级,每级宽高减半,内存连续排布;磁盘上.astc/.etc2/.ktx已按层级顺序编码,但Streaming Mipmap只在运行时按需上传GPU。
  2. 增量差异算法:bsdiff、hdiffz针对二进制流,但直接对压缩后的GPU纹理块(ASTC 6×6、ETC2 4×4)diff效果差;需先拆块、再按独立层级做分块diff,生成mipmap_x.patch
  3. Unity可编程导入管线TextureImporter.mipmapEnabledPlatformSettings可脚本化;AssetDatabase.SetImporterOverride<TextureImporter>可在打Bundle前注入自定义序列化数据。
  4. 热更框架适配
    • AssetBundle:把每层Mipmap打成独立mipmap_l0.bundlemipmap_l1.bundle,通过AssetBundle.LoadFromFileAsync按需加载,配合Texture2D.LoadRawTextureDataUploadTextureData覆盖;
    • Addressables:利用ResourceLocationMap动态指向远程URL,Catalog增量更新;
    • 小游戏:微信/字节平台支持WXDownLoadFile断点续传,需把patch文件放到小游戏分包CDN带缓存头
  5. 运行时GPU替换Texture2D.SetPixels32/SetPixelData只能整图上传;真正的层级局部更新需用CommandBuffer.IssuePluginEvent调用原生插件,在Metal/Vulkan层执行replaceRegion:mipmapLevel:;Unity 2022.1+开放Texture2D.CopyTexture支持同格式同尺寸拷贝,可跨线程减少卡顿。
  6. 版本控制与回滚:patch文件按资源MD5_平台_质量等级.mipmap_x.patch命名,服务器维护mipmap_patch_manifest.json,客户端比对lastPatchVersioncurrentVersion,失败时回滚至整包Bundle。

答案

分四步落地:
第一步:打基线
在CI里用ScriptableImporter把原始贴图导入为ASTC_6×6格式,开启Streaming Mipmap,同时导出每层的字节流与MD5,写入base_manifest.json

第二步:生成差异
版本迭代时,把新贴图同样分层导出,用自研BlockAlignDiff工具对每级做差异:

  • 对ASTC块对齐后做滚动hash,找出相同块;
  • 生成mipmap_l0.patchmipmap_l1.patch…大小仅为差异块+索引,平均可压缩到原层15%以下;
  • 把patch上传CDN,按资源名_平台_质量等级_层索引.patch命名。

第三步:热更下载
客户端启动时比对base_manifest与服务器patch_manifest,只下载发生变化的层级;使用UnityWebRequestGetDownloadHandler配合DownloadHandlerFile实现断点续传,下载后校验MD5。

第四步:运行时替换

  1. 加载原Bundle得到Texture2D主图;
  2. NativeArray<byte>读取patch,通过Texture2D.LoadRawTextureData写入临时贴图;
  3. 调用CommandBuffer.IssuePluginEvent传入mipmapLevelreplaceRegion参数,在Metal层执行replaceRegion:mipmapLevel:完成GPU端局部更新;
  4. 释放临时贴图内存,记录lastPatchVersion到本地PlayerPrefs,供下次启动差分。

若任一层patch校验失败,自动回滚到整包重新下载,保证玩家无感知

拓展思考

  1. 超分Mipmap:能否把低层patch换成深度学习超分后的数据?需在Native插件里做实时推理,权衡功耗与画质,适合高端机白名单。
  2. 与可编程渲染管线结合:URP/HDRP的Virtual Texture已支持页级更新,可把Mipmap差异映射到VT页,做到像素级增量,但需改SRP源码,面试可提思路。
  3. WebGL平台限制:WebGL无多线程,且CopyTexture仅支持glCopyImageSubData扩展;若扩展缺失,只能回退到整图上传,需提前在构建报告里标注风险。
  4. 合规与加密:国内渠道要求资源加密,差异patch同样需AES-128-CBC加密,密钥通过热更SDKSecuritySignature下发,避免外挂直接还原高清贴图。