解释ASTC纹理与ETC2回退策略
解读
面试官问的是“为什么”以及“怎么做”:
- 在国内 Android 碎片化严重的真机环境里,ASTC 并不是 100% 可用,必须有一条兜底路径;
- Unity 提供的 Quality Setting → Texture Compression 只是入口,真正的回退逻辑需要你在 打包管线(Scriptable Build Pipeline)+ 运行时检测 两端同时闭环;
- 回答时要体现你对 纹理内存占用、包体大小、加载耗时、热更新兼容性 四个维度的权衡,而不是单纯背“ASTC 比 ETC2 压缩率高”。
知识点
- ASTC 硬件支持率:
- Mali-T624 以后、Adreno 4xx 以后、PowerVR 6XT 以后才保证支持;
- 2024 年国内存量低端机(展讯、部分 MTK6739、骁龙425 以下)仍不支持 ASTC 6×6 以上 Block Size。
- ETC2 硬件支持率:
- OpenGL ES 3.0 强制支持,覆盖率 99.7%(国内安卓 4.3+)。
- Unity 纹理导入规则:
- 若平台设置里同时勾了 ASTC 与 ETC2,Unity 会生成两份 Chunk;
- 但 运行时只会加载一份,选择顺序由 SystemInfo.SupportsTextureFormat 决定,不是简单的“高版本就用 ASTC”。
- Scriptable Build Pipeline 回退钩子:
- 在 IPreprocessBuildWithReport 里扫描所有 TextureImporter,若目标平台为 Android 且 !PlayerSettings.GetUseDefaultGraphicsAPIs(BuildTarget.Android) 且 GLES2.0 在 Graphics API 列表里,则强制把 ASTC 改成 ETC2_RGB/ETC2_RGBA;
- 同时把原 ASTC 图集打进 StreamingAssets,供热更新脚本在 支持 ASTC 的设备上二次替换,实现“包体最小 + 运行时最优”。
- 内存与质量量化数据:
- 1024×1024 RGBA32 原图 4 MB;
- ASTC 6×6 0.59 MB,ETC2_RGBA 1 MB;
- 低端机 GPU 带宽瓶颈 > 存储瓶颈,因此回退到 ETC2 反而帧率更稳。
答案
“我们项目把 Android 纹理策略拆成 三层:
- 打包期:在 Scriptable Build Pipeline 的 PreProcess 阶段,用 SystemInfo.SupportsTextureFormat(TextureFormat.ASTC_6X6) 做编辑器模拟检测,把不支持 ASTC 的 Variant 直接剔除,避免双倍包体;
- 首次安装:默认加载 ETC2,首包大小降低 25%;
- 运行时:启动后 200 ms 内用 UnityWebRequest 下载设备专用清单,若检测到 ASTC 支持,则通过 Addressables 的 InitializeAsync 重新指向 ASTC 远程 Catalog,并在后台线程把 ETC2 贴花资源 异步卸载(Resources.UnloadUnusedAssets),实现零卡顿替换。
整个回退策略用 ScriptableObject 配置表 驱动,美术零感知,策划无需改表,线上崩溃率 < 0.02%。”
拓展思考
- iOS 端是否还需要 ETC2 回退?
- iPhone 5s 以上 100% 支持 ASTC,可直接舍弃 ETC2,但 WebGL 导出到微信小游戏时,微信内核仍可能降级到 GLES2.0,此时需要 ETC1+Alpha 拆分作为第二方案。
- HDR 场景下的 ASTC HDR 扩展:
- ASTC HDR 需要 Vulkan 1.1+ 或 Metal,国内 华为麒麟 710A 以下不支持,仍需 RGB9e5 或 R11G11B10 回退。
- 热更新粒度:
- 如果项目使用 YooAsset 或 ResourcePackage,可把 ASTC/ETC2 双份 SpriteAtlas 打成一个独立的 Package,通过 版本号 + 设备能力标签 做差分下载,节省 30% CDN 流量。