Skip to content

包体优化 ​

包体大小主要由什么组成? ​

Unity 游戏的包体不是只有代码,真正的大头通常是 资源。面试里可以这样答:包体主要由 引擎运行时、代码产物、游戏资源、Shader、第三方插件 SDK、平台相关文件 组成。

unity-package-size-composition

1. Unity 引擎运行时

比如 UnityPlayer、底层运行库、平台适配库。 这是 Unity 程序能跑起来的基础,哪怕你项目很小,也会有一部分固定大小。

如果是 IL2CPP,还会有 native 代码相关产物。

2. 代码产物

包括:

  • C# 编译后的程序集
  • IL2CPP 生成的 C++ 和 native 库
  • 第三方代码库
  • Lua、配置解析代码、热更框架代码

一般来说,代码不是包体最大头,但如果插件很多,体积也会明显上去。

3. 游戏资源

这是最容易变大的部分,包括:

  • 贴图
  • UI 图集
  • 模型 Mesh
  • 动画 AnimationClip
  • 音频 AudioClip
  • 视频
  • 字体
  • 场景
  • Prefab
  • 材质

面试要重点说:贴图、音频、视频、模型通常是包体优化优先级最高的几类资源。

4. Shader 和 Shader Variant

Shader 本身可能不大,但 Shader Variant 很容易膨胀。

比如一个 Shader 支持:

  • 是否开阴影
  • 是否开雾效
  • 是否开法线贴图
  • 是否开光照
  • 不同平台关键字

组合起来 Variant 数量会爆炸,导致包体变大,加载也变慢。

5. 第三方插件和 SDK

比如:

  • 广告 SDK
  • 登录 SDK
  • 支付 SDK
  • 统计 SDK
  • 推送 SDK
  • 崩溃收集 SDK

移动端还要注意不同 CPU 架构,比如 arm64-v8a、armeabi-v7a。如果架构库都打进去,包体会变大。

6. 平台文件和调试信息

比如 Android 的:

  • AndroidManifest
  • native so 库
  • 资源表
  • keystore 相关配置
  • 符号文件

正式包里一般不要带多余调试信息、Development Build、未裁剪符号文件。

面试高分回答

NOTE

包体大小主要由引擎运行时、代码产物、资源文件、Shader 变体、第三方 SDK 和平台相关文件组成。Unity 项目里资源通常是最大头,尤其是贴图、音频、模型、动画和视频。优化时我不会凭感觉删资源,而是先看 Build Report 或 Build Analyzer,找出占用最大的资源类型,再做贴图压缩、音频压缩、Shader Variant 裁剪、资源去重、Addressables 拆包,以及首包和热更包拆分。

Texture 压缩格式怎么选? ​

Texture 压缩格式的选择,本质是在 平台兼容、显示质量、显存占用、带宽、包体大小 之间做平衡。面试里不要只背格式名,要说出“为什么这么选”。

unity-texture-compression-format-choice

优先看平台

不同平台 GPU 支持的纹理压缩格式不一样。

移动端现在通常优先考虑:

  • Android:ASTC 优先,兼容方案可用 ETC2
  • iOS:现代设备优先 ASTC,老设备可能考虑 PVRTC
  • PC:常用 DXT/BC 系列,比如 DXT1、DXT5、BC7

简单记法:移动端优先 ASTC,Android 兼容 ETC2,PC 用 BC/DXT。

再看有没有透明通道

如果图片不需要透明,就不要用带 Alpha 的格式,因为 Alpha 会增加体积和内存。

常见选择:

  • 不透明贴图:选 RGB 格式
  • 透明贴图:选 RGBA 格式
  • ETC1:不支持 Alpha
  • ETC2 RGBA:支持 Alpha
  • ASTC:支持 RGB/RGBA,移动端很常用
  • DXT1:适合无 Alpha 或 1-bit Alpha
  • DXT5:适合完整 Alpha

比如 UI 图标有透明边缘,就不能随便用不支持 Alpha 的格式。

ASTC 怎么选?

ASTC 的特点是可以选择不同 block size。

常见理解:

  • ASTC 4x4:质量高,体积较大
  • ASTC 6x6:比较常用,质量和体积平衡
  • ASTC 8x8:更省空间,但画质会下降
  • ASTC 10x10 / 12x12:更小,但容易糊,适合不重要的远景或低频纹理

面试可以说:主角、UI、重要特效可以用更高质量,场景远景、低频纹理可以用更高压缩率。

不同资源怎么选

UI、文字、图标: 优先保证清晰度,压缩太狠会出现边缘脏、文字糊、渐变断层。

场景贴图: 可以更积极压缩,因为场景图往往数量大,是包体和显存大头。

法线贴图: 不要压得太狠,否则光照会出块状、凹凸错误。PC 上常见 BC5,移动端可以根据平台选合适的 ASTC/ETC2 格式。

特效贴图: 要注意透明区域和 Overdraw,压缩格式只是其中一部分,还要控制贴图尺寸和透明面积。

Crunch 是什么

Crunch 更偏向减少包体或下载体积,不等于 GPU 直接用 Crunch 格式。

它通常会在加载时解压成 GPU 可用的压缩格式,所以:

  • 好处:包体更小
  • 代价:加载时 CPU 解压成本更高
  • 适合:非频繁加载、对包体敏感的资源
  • 不适合:战斗中临时大量加载的关键资源

面试高分回答

TIP

Texture 压缩格式我会先按平台选,移动端优先 ASTC,Android 兼容可以用 ETC2,PC 用 DXT/BC 系列。然后看贴图是否需要 Alpha,不需要透明就不用 RGBA,避免浪费。接着按用途区分,UI 和文字优先清晰度,场景贴图优先体积和显存,法线贴图要避免压缩失真。ASTC 可以通过 4x4、6x6、8x8 调整质量和体积。最后一定要真机检查,因为压缩格式不只是影响包体,还会影响显存、带宽、加载速度和最终画质。

ASTC、ETC2、PVRTC 区别是什么? ​

它们都是 GPU 纹理压缩格式。目的都是让贴图更省 包体、显存、带宽,但它们的 平台支持、压缩质量、适用场景 不一样。

unity-astc-etc2-pvrtc-difference

ASTC

ASTC 是现在移动端很常用、也很推荐的压缩格式。

它的特点是 质量好、压缩率灵活、支持 Alpha。 比如你可以选:

  • ASTC 4x4:质量高,体积较大
  • ASTC 6x6:质量和体积比较平衡
  • ASTC 8x8:更省空间,但画质更糊

所以 ASTC 特别适合移动端项目里大部分贴图,比如角色、场景、UI、特效。

面试可以说:现代 Android 和 iOS 设备,优先考虑 ASTC。

ETC2

ETC2 更常用于 Android 兼容方案。

它比 ETC1 更强,因为 ETC1 不支持完整 Alpha,而 ETC2 可以支持 RGB,也可以支持 RGBA。

ETC2 的优点是:

  • Android GLES3 设备支持比较普遍
  • 支持透明
  • 兼容性比 ASTC 在某些 Android 设备上更稳

缺点是压缩质量和灵活性通常不如 ASTC。

面试可以说:如果目标 Android 设备不一定都支持 ASTC,可以考虑 ETC2 作为兼容方案。

PVRTC

PVRTC 主要是老 iOS 设备常见的压缩格式。

它的常见规格有:

  • PVRTC 2bpp
  • PVRTC 4bpp

PVRTC 的问题是压缩质量限制比较明显,尤其是:

  • UI 边缘容易脏
  • 渐变容易糊
  • 透明图可能有瑕疵
  • 细节贴图容易失真

现在如果目标是较新的 iOS 设备,通常更推荐 ASTC。

面试高分回答

可以这样说:

WARNING

ASTC、ETC2、PVRTC 都是 GPU 纹理压缩格式。ASTC 是现代移动端比较推荐的格式,支持 Alpha,质量好,而且可以通过 4x4、6x6、8x8 这种 block size 在质量和体积之间做平衡。ETC2 常作为 Android 兼容方案,比 ETC1 强,因为 ETC2 支持 Alpha。PVRTC 主要用于老 iOS 设备,但质量限制比较明显,UI、渐变和透明边缘容易出问题。所以实际项目里我会优先 ASTC,Android 兼容用 ETC2,只有需要兼容老 iOS 时才考虑 PVRTC。

音频压缩怎么选? ​

Unity 里音频压缩不是只看“文件小不小”,而是看 包体、内存、CPU 解码、加载速度、播放延迟 的平衡。

unity-audio-compression-choice

PCM

PCM 基本可以理解成“不压缩音频”。

优点是播放时几乎不需要解码,响应快、质量高。缺点是包体和内存占用很大。

适合:

  • 很短的 UI 点击音
  • 打击瞬间音效
  • 对延迟敏感的短音效

不适合:

  • BGM
  • 长语音
  • 大量长音频

ADPCM

ADPCM 是一种比较适合游戏短音效的压缩格式。

它比 PCM 小,解码成本也比较低,但是压缩率不如 Vorbis。

适合:

  • 技能音效
  • 受击音效
  • 脚步声
  • 频繁播放的短音效

面试里可以说:短音效如果既想省一点内存,又不想解码太贵,可以考虑 ADPCM。

Vorbis

Vorbis 是有损压缩,压缩率高,包体小,但播放或加载时有解码成本。

适合:

  • 背景音乐
  • 剧情语音
  • 角色长语音
  • 环境音

面试里可以说:长音频通常用 Vorbis,因为包体和内存更重要。

Load Type 怎么选

Decompress On Load:加载时解压到内存。 播放最稳、CPU 压力小,但内存占用大。适合短且频繁播放的音效。

Compressed In Memory:内存里保持压缩,播放时解码。 省内存,但播放时有 CPU 解码开销。适合中等长度、播放不特别频繁的音频。

Streaming:边读边播。 内存占用低,适合 BGM 和很长的语音。但不要同一时间 Streaming 太多音频,否则可能有 IO 压力。

Sample Rate 怎么调

不是所有音频都需要 44100 Hz。

比如:

  • 普通语音可以降低采样率
  • 低频环境音可以降低采样率
  • 很短的提示音可以适当压缩
  • 高品质 BGM 可以保留更高采样率

采样率越高,数据越大;声道越多,占用也越大。

Force To Mono

很多音效其实不需要立体声,比如按钮音、普通攻击音、拾取音。

如果开 Force To Mono,双声道可以变单声道,数据量可能直接减少接近一半。

面试高分回答

可以这样说:

IMPORTANT

音频压缩我会按用途来选。短音效重视播放响应和 CPU 开销,一般用 PCM 或 ADPCM,并配合 Decompress On Load;长音乐和长语音重视包体和内存,一般用 Vorbis,并配合 Streaming。中等长度、不频繁播放的音频可以用 Compressed In Memory。除此之外,还会根据音频内容降低 Sample Rate,普通音效开启 Force To Mono,关键音效预加载,避免首次播放卡顿。总体思路是短音效用空间换速度,长音频用解码和流式加载换内存。

Mesh 压缩有什么风险? ​

Mesh 压缩的本质是:降低顶点数据精度。它可以减少包体和模型数据大小,但风险是模型的 顶点位置、法线、切线、UV 可能出现误差。

unity-mesh-compression-risks

1. 模型可能变形

Mesh 压缩会对顶点位置做近似保存。压缩等级越高,精度损失越明显。

可能出现:

  • 轮廓变歪
  • 边缘抖动
  • 小细节丢失
  • 模型接缝裂开
  • 远离原点的大场景精度问题更明显

比如细长的武器、尖角建筑、小装饰物,压缩后很容易看出形状变化。

2. 法线和切线可能出问题

法线 Normal 决定光照方向,切线 Tangent 常用于法线贴图。

如果它们被压缩得太狠,可能出现:

  • 光照变脏
  • 高光方向不对
  • 法线贴图效果异常
  • 金属材质、皮肤材质看起来怪

所以有法线贴图、PBR 材质、高光明显的模型,不建议随便开高压缩。

3. UV 可能产生误差

UV 是贴图坐标。UV 精度下降后,可能出现:

  • 贴图轻微偏移
  • 图集边缘串色
  • 接缝明显
  • Lightmap 采样错误
  • UI 或标志类模型边缘变脏

尤其是使用图集、Lightmap UV、精细贴图的模型,要谨慎。

4. 骨骼动画可能出问题

角色模型是 Skinned Mesh,顶点会随着骨骼运动。

如果顶点精度下降,可能导致:

  • 动画时皮肤穿插
  • 面部表情变形异常
  • 手指、脸部这种细节部位出问题
  • BlendShape 效果不准确

所以主角、NPC、脸部模型、带 BlendShape 的模型,一般不要使用太高的 Mesh 压缩。

5. 碰撞和挂点可能不准

如果你用 Mesh 做精确碰撞,压缩后顶点位置变了,碰撞形状也可能不准。

风险包括:

  • 子弹碰撞不准确
  • 地形边缘卡住
  • 武器挂点偏移
  • 特效挂点看起来错位

所以碰撞相关 Mesh、武器、坐骑、挂点密集的模型,要特别小心。

6. 什么模型适合压缩

比较适合压缩:

  • 远景模型
  • 静态场景小物件
  • 不重要的装饰物
  • 低面数、低精度要求模型
  • 玩家不容易近距离观察的模型

不太适合压缩:

  • 主角模型
  • 脸部模型
  • 武器模型
  • 精确碰撞 Mesh
  • 法线贴图明显的模型
  • Lightmap 要求高的模型
  • 带 BlendShape 的模型

面试高分回答

可以这样说:

CAUTION

Mesh 压缩能减少模型数据和包体,但它不是无损的,本质是降低顶点属性精度。风险主要有顶点位置误差导致模型变形,法线和切线误差导致光照、高光、法线贴图异常,UV 误差导致贴图偏移、接缝和 Lightmap 问题。对于主角、脸、武器、精确碰撞、BlendShape、法线贴图明显的模型,我会谨慎压缩;对于远景、静态、不重要装饰物,可以适当开启压缩。最终一定要在真机和目标画质下检查,而不是只看包体减少了多少。

Shader Variant 为什么会爆炸? ​

Shader Variant 爆炸的本质是:各种开关组合在一起不是加法增长,而是乘法增长。

unity-shader-variant-explosion

Variant 是什么

一个 Shader 里可能有很多功能开关,比如:

  • 是否使用法线贴图
  • 是否开启阴影
  • 是否开启雾效
  • 是否开启自发光
  • 是否开启 GPU Instancing
  • 是否使用额外灯光

Unity 会根据这些开关生成不同版本的 Shader,这些版本就叫 Shader Variant。

为什么会爆炸

比如一个 Shader 有 8 个二选一开关,每个开关都有开和关:

2^8 = 256

如果这个 Shader 还有 3 个 Pass:

256 x 3 = 768

如果还要支持 2 个平台:

768 x 2 = 1536

真实项目里还会叠加光照、阴影、雾效、渲染管线、质量设置、平台 API,所以数量会非常快地膨胀。

multi_compile 和 shader_feature 的区别

multi_compile 比较危险。 它会告诉 Unity:这些变体都要准备,即使项目里没有用到,也可能被打进去。

shader_feature 更适合可选功能。 Unity 构建时可以尝试裁剪没用到的变体。

所以面试可以说:能用 shader_feature 的地方,不要无脑用 multi_compile。

爆炸有什么后果

主要有三个问题:

  1. 包体变大 变体越多,最终构建产物越大。
  2. 构建变慢 Unity 要编译大量 Shader 版本,CI 打包也会变慢。
  3. 运行时卡顿 如果某个变体没有提前准备,运行时第一次用到时可能出现 Shader 编译卡顿,比如放技能、切场景、换皮肤时突然卡一下。

怎么优化

常见做法:

  • 减少无用 Keyword
  • 少用 multi_compile
  • 可选功能尽量用 shader_feature
  • 使用 Local Keyword,减少全局关键字污染
  • 裁剪不用的阴影、雾效、光照模式
  • 拆分复杂 Shader,不要一个 Shader 包所有功能
  • 使用 Shader Variant Collection 做预热
  • 用 Build Report 或 Shader Variant Log 分析数量
  • URP/HDRP 里关闭没用的管线特性

面试高分回答

NOTE

Shader Variant 爆炸是因为 Shader Keyword、Pass、光照阴影、雾效、Instancing、平台和渲染管线配置会组合生成不同版本。它不是线性增长,而是乘法增长。比如 8 个二选一 Keyword 就是 256 个变体,再乘上 Pass、平台和管线配置,数量会很快失控。后果是包体变大、构建变慢、运行时可能 Shader 编译卡顿。优化上我会减少 Keyword,少用 multi_compile,多用 shader_feature,开启变体裁剪,拆分复杂 Shader,并对必要变体做预热。

如何裁剪未使用资源? ​

裁剪未使用资源,不能简单理解成“项目里没看到引用就删”。Unity 里很多资源可能是 动态加载、配置表引用、热更引用、Addressables 引用,直接删很容易线上 Missing。

unity-unused-resource-stripping

正确流程

第一步,找构建入口。 比如 Build Settings 里的场景、Addressables Group、AssetBundle 构建规则、Resources 目录、热更资源列表。

第二步,分析依赖链。 场景引用 Prefab,Prefab 引用材质,材质引用贴图,动画引用 Avatar、骨骼、事件,ScriptableObject 又可能引用一批配置资源。

第三步,找可疑资源。 如果一个资源不在构建入口依赖链里,也不在白名单里,也没有被配置表或代码动态加载,就可以标记为“疑似未使用”。

第四步,先隔离再删除。 不要一上来直接删,可以先移动到隔离目录,打包、启动、切场景、跑主流程,确认没有 Missing Reference 再真正删除。

Unity 里最容易误判的地方

Resources 目录: Resources 下面的资源一般都会进包,即使你没在场景里直接引用。

Addressables: 资源可能通过 Address 地址、Label、配置表加载,不能只看 Inspector 引用。

AssetBundle: 资源可能由打包规则收集进去,还要检查 Bundle 之间的依赖和重复资源。

字符串路径加载: 比如 Resources.Load("Effect/Hit01"),编辑器依赖分析不一定能准确知道它会被用到。

配置表引用: 很多项目的怪物、技能、UI、剧情资源都是配置表里写路径加载的,这类资源必须加入白名单或从配置表反查。

常用工具

可以用这些方式辅助分析:

  • Build Report 看最终包体里资源占用
  • Editor.log 查看打包资源信息
  • Build Analyzer 找大资源和重复资源
  • AssetDatabase.GetDependencies 查依赖链
  • Addressables Analyze 检查重复打包和依赖问题
  • 自研资源扫描工具,反查配置表、Prefab、场景、Addressables

面试高分回答

TIP

裁剪未使用资源我不会直接按“编辑器里没有引用”删除,而是先确定所有构建入口,包括场景、Resources、Addressables、AssetBundle、配置表和动态加载路径。然后建立资源依赖图,找出没有被任何入口依赖、也不在白名单里的资源。对疑似未使用资源先隔离,不直接删除,再通过打包、启动、切场景、主流程自动化测试来验证。最后配合 Build Report、Addressables Analyze 和自研扫描工具持续检查,避免因为字符串加载、热更资源、配置表引用导致误删。

Addressables 如何分析包体? ​

Addressables 分析包体,重点不是只看“某个资源多大”,而是看 Bundle 大小、依赖关系、重复资源、Group 分组、Local/Remote 边界。

unity-addressables-package-analysis

第一步:先看构建结果

不要只看 Project 目录里的资源大小,要看 Addressables 真正 Build 出来的结果。

重点看:

  • 哪些 Bundle 最大
  • 每个 Bundle 里有哪些 Asset
  • Asset 依赖了哪些资源
  • 哪些资源被重复打进多个 Bundle
  • 哪些资源进了首包,哪些资源进了远程包

第二步:看 Build Layout Report

Build Layout Report 可以看到:

  • Bundle 列表
  • Bundle 大小
  • 每个 Bundle 包含哪些资源
  • 每个资源的依赖
  • 哪些资源被哪个 Addressable Asset 带进去
  • 隐式依赖是否过大

比如一个 Prefab 本身不大,但它引用了材质,材质引用了大贴图,最后真正变大的可能是贴图依赖。

第三步:用 Analyze 查重复依赖

Addressables 的 Analyze 工具可以检查重复 Bundle 依赖。

最常见的问题是:

两个不同 Group 里的 Prefab 都引用了同一张贴图。 如果这张贴图没有单独 Addressable 化,可能会被分别打进两个 Bundle,导致包体重复。

解决思路:

  • 公共贴图单独放到公共 Group
  • 公共材质单独管理
  • 公共 Prefab、字体、Shader 单独成包
  • 避免多个 Bundle 各自携带同一份依赖

第四步:检查 Group 分组是否合理

Group 分组会直接影响包体结构。

常见问题:

  • 把不相关资源 Pack Together,导致一个小资源加载带出一大包
  • 把强相关资源拆太散,导致加载时请求很多 Bundle
  • 公共资源没有独立分组,造成重复依赖
  • 首包 Group 塞了太多非必要资源
  • 远程资源没有按玩法、章节、活动拆分

面试可以说:Group 设计不是越细越好,也不是越粗越好,要根据加载场景和更新粒度设计。

第五步:对比优化前后

一次优化是否有效,要用数据证明。

可以对比:

  • 首包大小是否下降
  • 远程包大小是否合理
  • Bundle 数量是否变化
  • 重复资源是否减少
  • 加载请求数量是否变多
  • 峰值内存是否变化
  • 下载体积是否下降

不能只说“我删了一些资源”,要说“通过报告对比,首包减少了多少,重复依赖减少了多少”。

面试高分回答

IMPORTANT

Addressables 分析包体我会先 Clean Build,拿到真实构建结果,然后看 Build Layout Report,分析每个 Bundle 的大小、包含资源和依赖链。接着用 Analyze 检查 Duplicate Bundle Dependencies,找出公共贴图、材质、字体、Shader 是否被多个 Bundle 重复打包。然后根据加载场景调整 Group,比如公共资源单独成包,大资源放远程包,首包只保留启动必要资源。优化后我会保留前后两份构建报告,对比首包大小、远程包大小、重复资源、Bundle 数量和加载请求数量,避免只优化包体却把加载性能搞差。

首包和分包策略怎么设计? ​

首包和分包的核心目标是:首包尽量小,首次体验完整,后续资源按需下载,公共依赖不重复,热更版本可控。

unity-initial-package-subpackage-strategy

首包放什么

首包只放玩家第一次打开游戏必须用到的东西:

  • 启动场景
  • 登录界面
  • 基础 UI
  • 核心代码
  • 基础配置表
  • 基础 Shader
  • 通用字体
  • 新手流程必需资源
  • 首战或最早玩法必需资源

不要把后期地图、活动资源、大量皮肤、全量语音、全部角色都塞进首包。

分包怎么拆

常见拆法:

  • 按场景拆:主城、战斗场景、副本场景
  • 按玩法拆:PVP、PVE、公会、家园、活动
  • 按章节拆:第一章、第二章、第三章
  • 按角色拆:角色模型、技能特效、语音
  • 按语言拆:中文、英文、日文语音和文本
  • 按清晰度拆:高清资源、低配资源
  • 按活动拆:限时活动单独热更包

面试里要说:不是拆得越碎越好。拆太碎会导致加载请求多、依赖复杂;拆太粗又会导致下载大包。

公共依赖要单独管理

很多包会共用资源,比如:

  • 公共贴图
  • 公共材质
  • 公共 Shader
  • 字体
  • 通用 UI 图集
  • 通用音效
  • 通用特效

这些资源最好单独成公共包,否则多个分包可能重复打进同一份资源,包体会膨胀。

下载时机怎么设计

可以分几类:

启动前必须下载: 版本清单、基础配置、登录必要资源。

进入玩法前下载: 比如玩家要进某个副本,提前检查这个副本的场景、怪物、音效、特效是否已下载。

后台预下载: 玩家停留在大厅时,可以悄悄下载后续章节、常用资源。

按需下载: 玩家点击某个活动、皮肤、语音包时再下载。

风险控制

分包一定要考虑异常情况:

  • 网络断开怎么办
  • 下载失败怎么办
  • Hash 校验失败怎么办
  • 缓存损坏怎么办
  • 版本清单和资源版本不一致怎么办
  • 下载到一半退出游戏怎么办
  • 资源更新失败是否能回滚

成熟一点的方案会有版本清单、Hash 校验、断点续传、失败重试、缓存清理和回滚机制。

面试高分回答

WARNING

首包和分包我会先按资源使用时机分类。首包只放启动、登录、新手流程、首战和核心系统必须用到的资源,保证玩家首次进入体验完整,但不把后期地图、活动、皮肤、语音等资源放进去。分包一般按场景、玩法、章节、活动、语言和清晰度拆分。公共贴图、字体、Shader、材质、通用 UI 会单独放公共包,避免多个分包重复依赖。下载策略上,启动阶段只拉版本清单和必要资源,进入玩法前检查并下载对应分包,空闲时后台预下载。最后通过版本清单、Hash 校验、缓存、重试和回滚机制保证热更稳定。

Android 和 iOS 包体差异有哪些? ​

Android 和 iOS 包体差异有哪些?

Unity 项目在 Android 和 iOS 上包体不一样,主要差异来自 包格式、原生库、纹理压缩格式、平台 SDK、商店分发机制。

unity-android-ios-package-differences

Android 包体特点

Android 常见是 APK 或 AAB。

里面通常有:

  • classes.dex
  • libil2cpp.so
  • assets
  • res
  • AndroidManifest.xml
  • 第三方 AAR / JAR / so

Android 包体很容易被 ABI 影响。

比如同时打:

  • armeabi-v7a
  • arm64-v8a

如果是 Universal APK,可能会把多个架构的 so 都放进去,包体会明显变大。 如果使用 AAB,商店可以按设备架构、语言、屏幕密度拆分下发,用户实际下载体积会更小。

iOS 包体特点

iOS 常见是 IPA。

里面通常有:

  • Mach-O 可执行文件
  • Frameworks
  • Unity Data
  • AssetCatalog
  • 资源 bundle
  • 插件相关 framework 或 xcframework

Unity iOS 一般使用 IL2CPP,C# 代码最终会变成 native 产物。 iOS 也有 App Thinning,商店会尽量只给用户下发当前设备需要的资源和架构。

纹理压缩差异

Android 常见:

  • ASTC
  • ETC2
  • 老设备可能涉及 ETC1

iOS 常见:

  • ASTC
  • 老设备可能涉及 PVRTC

所以同一套贴图,在 Android 和 iOS 上可能会被压成不同格式,最终包体和显存占用也会不一样。

插件 SDK 差异

Android 插件经常带:

  • AAR
  • JAR
  • DEX
  • res
  • so

这些会增加代码体积、资源体积和 native 库体积。

iOS 插件经常带:

  • Framework
  • xcframework
  • .bundle 资源
  • 原生静态库或动态库

如果 SDK 接得多,比如登录、支付、广告、统计、推送,两端包体都会明显增加,但组成不一样。

面试高分回答

CAUTION

Android 和 iOS 包体差异主要来自平台打包结构。Android 是 APK 或 AAB,里面有 dex、res、assets、libil2cpp.so 和第三方 AAR、so,包体很容易受 ABI 数量影响;如果打 Universal APK,同时包含 arm64-v8a 和 armeabi-v7a,体积会变大,而 AAB 可以按设备拆分下发。iOS 是 IPA,主要包含 Mach-O 可执行文件、Framework、Unity Data 和资源 bundle,Unity iOS 通常走 IL2CPP。资源方面,两端纹理压缩格式也不同,Android 常用 ASTC 或 ETC2,iOS 常用 ASTC,老设备可能用 PVRTC。优化时两端都要看贴图、音频、Shader Variant、插件 SDK,但 Android 重点关注 ABI 和 AAB,iOS 重点关注 Framework、架构裁剪和 App Thinning。

文章评价

读完这篇,留下你的看法

暂无审核通过的评价。

登录账号后才能评价。

本站访客数0总站访问量0本页访问量0