1. 代码包体占用
这里的代码不仅包括项目中的业务代码,还包括 .NET 框架、Packages 及第三方插件中的代码
由于暂时没找到办法统计各模块的代码包体大小,这里只对比开启不同裁剪级别后构建的包体总大小
最低裁剪级别时包体大小:
最高裁剪级别时包体大小:
可以看到最低和最高裁剪级别构建后的包体大小差距并不大,仅有 3.2M,此次对比并没有使用空包,虽然空包的差距更明显,但实际开发过程中不存在零行代码的情况,所以对比空包意义不大
而且随着业务代码的增多,这个差距也会越来越小,但本着蚊子再小也是肉的原则,3M左右的优化空间也足够慎重对待,尤其是对于微信小游戏等平台
2. 代码裁剪
对于代码而言,想要减少对应包体,只能减少代码量,Unity 提供了代码裁剪功能,可以根据不同需求设置不同裁剪级别,从而减少构建后的包体大小
1. 托管代码剥离
托管代码剥离将从构建中删除未使用的代码,从而可以显著减小最终构建大小。使用 IL2CPP 脚本后端时,托管代码剥离还可以减少构建时间,因为需要转换为 C++ 并进行编译的代码减少。托管代码剥离将从托管程序集(包括从项目中的 C# 脚本构建的程序集、包含在包和插件中的程序集以及 .NET 框架中的程序集)中删除代码
托管代码剥离的工作方式是对项目中的代码进行静态分析,检测出在执行过程中永远无法访问的类、类成员甚至函数的某些部分。可以通过 Player Settings 窗口中的 Managed Stripping Level 设置(在 Optimization 部分)来控制 Unity 删除无法访问的代码的激进程度
重要信息:当代码(或插件中的代码)使用反射来动态查找类或成员时,代码剥离工具不能总是检测出项目是否正在使用这些类或成员,因此可能会删除它们。要声明某个项目正在使用这样的代码,请使用 link.xml 文件或 Preserve 属性
1. 裁剪级别
使用项目的 Player Settings 中的 Managed Stripping Level 选项来控制 Unity 删除未使用代码的激进程度
属性 | 功能 |
---|---|
Minimal | Unity 仅搜索 UnityEngine 和 .NET 类库中未使用的代码。 Unity 不会删除任何用户编写的代码。此设置最不可能导致任何意外的运行时行为。此设置对于可用性优先于构建大小的项目很有用。如果您使用 IL2CPP 脚本后端,则这是默认设置 |
Low | Unity 会搜索一些用户编写的程序集以及所有 UnityEngine 和 .NET 类库以查找未使用的代码。此设置应用一组规则,删除一些未使用的代码,但最大限度地减少意外后果的可能性,例如使用反射的运行时代码的行为发生变化 |
Medium | Unity 部分搜索所有程序集以查找无法访问的代码。此设置应用一组规则,去除更多类型的代码模式以减少构建大小。尽管 Unity 不会删除所有可能无法访问的代码,但此设置确实会增加不良或意外行为更改的风险 |
High | Unity 对所有程序集执行广泛搜索,以查找无法访问的代码。在此设置下,Unity 会优先考虑减小大小而不是代码稳定性,并删除尽可能多的代码。与较低剥离水平相比,此搜索可能需要更长的时间。仅对紧凑构建尺寸极其重要的项目使用此设置。彻底测试您的应用程序并仔细使用 Preserve 属性和 link.xml 文件,以确保 Unity 链接器不会删除重要代码 |
更多信息请参阅官方文档:「https://docs.unity3d.com/cn/2021.2/Manual/ManagedCodeStripping.html」
2. 防止裁剪
在开启最高裁剪级别后,构建运行时,有可能会报错无法找到类默认构造函数:
报错内容具体如下:
MissingMethodException: Default constructor not found for type xxx at System.RuntimeType.CreateInstanceMono (System.Boolean nonPublic, System.Boolean wrapExceptions) [0x00000] in <00000000000000000000000000000000>:0
这可能是因为项目中通过反射方式使用该类,构建时 UnityLinker 没有检测出该类导致被裁剪掉,项目中可以通过以下两种方式来防止该情况:
Preserve 属性:直接在源代码中标记要保留的元素
link.xml 文件:声明应如何保留程序集中的元素
具体使用方法请参阅官方文档:「https://docs.unity3d.com/cn/2021.2/Manual/ManagedCodeStripping.html」
3. 团结引擎
团结引擎为了优化在微信小游戏平台的性能,增加了引擎轻量化特性,其中包括对引擎代码的进一步剔除
1. 引擎代码剔除
引擎内部的一些功能点,即使未被使用到,也不会在构建时被自动剔除。微信小游戏平台对WASM大小比较敏感,为此我们增加了引擎代码剔除功能,可以针对这些功能点进行主动移除
目前支持剔除的功能点:LightProbe、多种纹理格式的运行时解压缩(DXT、ETC、ASTC)、FreeType中SFNT格式的PNG支持
更多信息请参阅官方文档:「https://docs.unity.cn/cn/tuanjiemanual/Manual/EngineStrip.html」
2. Built-in Package 剔除
引擎的一些内建功能模块,默认情况下是启用的。对于小游戏来说,很可能是不需要的。用户可以手动关闭这些功能,来彻底移除它们
3. 实测结果
但是经过本人实测,同一个项目,配置完全相同的情况,团结引擎开启一系列轻量化特性后,最终发布到微信小游戏的包体比 2021.3.x 版本大 1.5M,如果是我开启的姿势不正确的话,还请大佬们指点一二
4. HybridCLR
除了减少代码总量外,还可以对代码(Assembly)按需加载,从而减少首包大小,减少启动时间等
关于程序集和 HybridCLR,感兴趣的小伙伴可以参阅官方文档,后续有时间再详细介绍
程序集:「https://docs.unity3d.com/cn/2021.2/Manual/ScriptCompilationAssemblyDefinitionFiles.html」
HybridCLR: 「https://hybridclr.doc.code-philosophy.com」