3.4 包体优化与裁剪:每一兆字节都要答辩

核心结论

应用商店对很多地区仍限 100~150MB 下载(超了走分包/按需下载)。移动包体必须当作"钱"来管理:每个资源都要说明自己凭什么占这几兆。Android 的包体瘦身边际收益最高——官方有专门一页讲缩减 Android 包体(https://www.wanxiangyundang.top/read/unreal-engine-5-8-docs/reducing-android-binary-size-i-20a5),先读它,再做下面这些流程。

包体解剖:钱花在哪了

打包后用 UnrealPak 工具或者引擎的报告查看各目录占用。经验分布:

大头 占比(典型) 优先治理
贴图 45~60% ★★★★★
音频 10~20% ★★★★
动画 5~10% ★★★
静态网格 5~15% ★★★
着色器/材质 5~10% ★★
其他(字体/UI 等) 5% ★

治理顺序按占比从大到小,先贴图后一切。

贴图瘦身五板斧

  1. 降最大尺寸:角色 2048、场景物 1024、小道具 512(见 0303 规范表)。
  2. 压缩格式选对:Android 用 ASTC(比 ETC 兼容好且质量高),iOS 用 ASTC。注意 ASTC 在老设备(<Android 5.0)不支持,要给降级方案(ETC2)。
  3. 通道打包:四张灰度图合一(见 0201)。
  4. 裁 mips:Texture -> Never Stream 与 Run-time Virtual Texturing 按需勾。
  5. UI 图集化:散碎小图合并大图,省元数据也省内存。

音频瘦身

  • 长音乐用流式播放(Streaming),不一次性载入。
  • 音效采样率降到 22050Hz(手机扬声器 听不出 44100 的区别)。
  • 格式:过渡用 ADPCM/OGG。
  • 裁掉静音段(多数引擎/工具导出时自动,UE 用 SoundCue 的 Trim 或外部工具)。

裁剪:引擎功能做减法

裁剪项 设置/做法 节省
未用插件 Packaging 时排除非必需插件 数十~百 MB
编辑器数据 打 Shipping,不打包 Dev/Editor 资产 上百 MB
未用目标平台 只编目标平台 shader 显著
ini 裁剪 [Core.System] 去掉不用的模块 小
字体子集化 只包用到的字符集(尤其中文) 数十 MB

中文字体是大头:完整中文字体动辄 20~100MB。用 Font Face 子集化或在线字体方案,只打进常用 3000~7000 字。

常见坑与解法

坑 1:AAB 打出来比预期大

原因:默认 AAB 里同时带 ARM32/ARM64,shader 多份。

解法:用 ABI split(Google Play 的多 APK)或只保 ARM64(现代机全覆盖)。详见 https://www.wanxiangyundang.top/read/unreal-engine-5-8-docs/reducing-android-binary-size-i-20a5。

坑 2:贴图明明是 1024,包里还是占 10MB

原因:mip 全部内嵌 + 无压缩格式。

解法:确认压缩格式(ASTC)、确认开启了 mip streaming、No linger on filesystem 的导出模式。

坑 3:Shader 缓存膨胀

原因:材质一变就重编,shipping 包带了一堆未用 permutation。

解法:开启 Shader Compression;用 PSO Cache(Pipeline State Object 预编译清单),既缩包体又减少首次进入卡顿——这是一举两得的事。

相关节点速查

  • 查包内容:UnrealPak <pakfile> -list(或 Archive 工具)
  • 平台压缩:Texture Compression Settings(ASTC)
  • 字体子集:字体编辑器的 Subset 或离线工具

心得:包体优化是"工程师做一次、全团队受益"的投入。我们项目曾经把 1.2GB 的包压到 380MB,多做的事只有:贴图规范+ASTC+字体子集+关插件。省下的每一兆都是买量成本的降低。