Unity | 优化专项-包体 | 代码

avatar
作者
筋斗云
阅读量:0

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 删除未使用代码的激进程度

属性功能
MinimalUnity 仅搜索 UnityEngine 和 .NET 类库中未使用的代码。 Unity 不会删除任何用户编写的代码。此设置最不可能导致任何意外的运行时行为。此设置对于可用性优先于构建大小的项目很有用。如果您使用 IL2CPP 脚本后端,则这是默认设置
LowUnity 会搜索一些用户编写的程序集以及所有 UnityEngine 和 .NET 类库以查找未使用的代码。此设置应用一组规则,删除一些未使用的代码,但最大限度地减少意外后果的可能性,例如使用反射的运行时代码的行为发生变化
MediumUnity 部分搜索所有程序集以查找无法访问的代码。此设置应用一组规则,去除更多类型的代码模式以减少构建大小。尽管 Unity 不会删除所有可能无法访问的代码,但此设置确实会增加不良或意外行为更改的风险
HighUnity 对所有程序集执行广泛搜索,以查找无法访问的代码。在此设置下,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」

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!