如何增量Patch贴图Mipmap
解读
国内上线游戏迭代节奏极快,动辄周更、双周更,而包体大小直接决定渠道分发成本与玩家转化率。贴图往往占包体50%以上,全量替换浪费流量与CDN费用,因此面试官想确认两点:
- 是否理解Unity贴图Mipmap链在磁盘与内存中的存储方式;
- 能否设计一套可灰度、可回滚、可断点续传的增量Patch管线,把“只换有差异的Mipmap层级”落地到iOS/Android原生包、小游戏分包及AssetBundle热更场景。
知识点
- Mipmap链数据结构:Unity将0级原图向下采样生成1~n级,每级宽高减半,内存连续排布;磁盘上
.astc/.etc2/.ktx已按层级顺序编码,但Streaming Mipmap只在运行时按需上传GPU。 - 增量差异算法:bsdiff、hdiffz针对二进制流,但直接对压缩后的GPU纹理块(ASTC 6×6、ETC2 4×4)diff效果差;需先拆块、再按独立层级做分块diff,生成
mipmap_x.patch。 - Unity可编程导入管线:
TextureImporter.mipmapEnabled与PlatformSettings可脚本化;AssetDatabase.SetImporterOverride<TextureImporter>可在打Bundle前注入自定义序列化数据。 - 热更框架适配:
- AssetBundle:把每层Mipmap打成独立
mipmap_l0.bundle、mipmap_l1.bundle,通过AssetBundle.LoadFromFileAsync按需加载,配合Texture2D.LoadRawTextureData与UploadTextureData覆盖; - Addressables:利用
ResourceLocationMap动态指向远程URL,Catalog增量更新; - 小游戏:微信/字节平台支持
WXDownLoadFile断点续传,需把patch文件放到小游戏分包或CDN带缓存头。
- AssetBundle:把每层Mipmap打成独立
- 运行时GPU替换:
Texture2D.SetPixels32/SetPixelData只能整图上传;真正的层级局部更新需用CommandBuffer.IssuePluginEvent调用原生插件,在Metal/Vulkan层执行replaceRegion:mipmapLevel:;Unity 2022.1+开放Texture2D.CopyTexture支持同格式同尺寸拷贝,可跨线程减少卡顿。 - 版本控制与回滚:patch文件按
资源MD5_平台_质量等级.mipmap_x.patch命名,服务器维护mipmap_patch_manifest.json,客户端比对lastPatchVersion与currentVersion,失败时回滚至整包Bundle。
答案
分四步落地:
第一步:打基线
在CI里用ScriptableImporter把原始贴图导入为ASTC_6×6格式,开启Streaming Mipmap,同时导出每层的字节流与MD5,写入base_manifest.json。
第二步:生成差异
版本迭代时,把新贴图同样分层导出,用自研BlockAlignDiff工具对每级做差异:
- 对ASTC块对齐后做滚动hash,找出相同块;
- 生成
mipmap_l0.patch、mipmap_l1.patch…大小仅为差异块+索引,平均可压缩到原层15%以下; - 把patch上传CDN,按
资源名_平台_质量等级_层索引.patch命名。
第三步:热更下载
客户端启动时比对base_manifest与服务器patch_manifest,只下载发生变化的层级;使用UnityWebRequest的GetDownloadHandler配合DownloadHandlerFile实现断点续传,下载后校验MD5。
第四步:运行时替换
- 加载原Bundle得到
Texture2D主图; - 用
NativeArray<byte>读取patch,通过Texture2D.LoadRawTextureData写入临时贴图; - 调用
CommandBuffer.IssuePluginEvent传入mipmapLevel与replaceRegion参数,在Metal层执行replaceRegion:mipmapLevel:完成GPU端局部更新; - 释放临时贴图内存,记录
lastPatchVersion到本地PlayerPrefs,供下次启动差分。
若任一层patch校验失败,自动回滚到整包重新下载,保证玩家无感知。
拓展思考
- 超分Mipmap:能否把低层patch换成深度学习超分后的数据?需在Native插件里做实时推理,权衡功耗与画质,适合高端机白名单。
- 与可编程渲染管线结合:URP/HDRP的
Virtual Texture已支持页级更新,可把Mipmap差异映射到VT页,做到像素级增量,但需改SRP源码,面试可提思路。 - WebGL平台限制:WebGL无多线程,且
CopyTexture仅支持glCopyImageSubData扩展;若扩展缺失,只能回退到整图上传,需提前在构建报告里标注风险。 - 合规与加密:国内渠道要求资源加密,差异patch同样需AES-128-CBC加密,密钥通过热更SDK的
SecuritySignature下发,避免外挂直接还原高清贴图。