伊隆·马斯克|Unity 2020 LTS更轻松的实现托管代码剥离工作流

伊隆·马斯克|Unity 2020 LTS更轻松的实现托管代码剥离工作流

文章图片


我们都知道托管代码剥离是构建游戏作品过程中的关键步骤 。 该步骤有助于减小应用程序二进制文件的大小 。 它通过移除未使用的代码来实现 。
通过删除代码 , 用户可以确保这些代码不会被编译或包含在最终的构建中 。 虽然这会稍微减少使用IL2CPP后端运行项目的内存使用 , 但是在运行时 , 在较高的托管代码剥离级别下 , 总会有丢失类型和方法的风险 。
在整个构建过程中 , 经常有一些代码是无效的 , 这些无效代码会被剥离 。 手动将所需的程序集添加到link.xml文件不是防止它们被移除的最简单方法 。 在本文中将为大家介绍这些技巧和最佳的应用方法 , 以便大家有效改进托管代码剥离工作流 。

使用Unity链接器剥离托管代码
当我们使用IL2CPP脚本后端时 , 删除未使用的代码尤其重要 。 Unity链接器——Mono IL linker将执行静态分析以剥离托管代码 。
【伊隆·马斯克|Unity 2020 LTS更轻松的实现托管代码剥离工作流】Unity支持IL2CPP低、中、高三个级别的托管代码剥离 。 托管代码剥离指导手册解释了代码剥离过程是如何工作的 , 哪些因素剥离了某些代码 , 以及剥离级别如何彼此不同 。 简而言之:代码剥离级别越高 , 链接器就越难找到并移除未使用的代码 。 因此我们可以在项目的“播放器设置”中修改“受管理的剥离级别”以快速找到那些被视为未使用的代码 。
链接器利用静态分析来识别未使用的代码 , 当某个对象的类型只在运行时定义时 , 静态分析不能覆盖所有情况 。 这些案例会导致虚假的积极性结果 。 虽然编译时可能没有任何对类或方法的引用 , 但运行时代码的某些部分仍然需要该类或方法 。 在这种情况下 , 使用反射是一个很好的例子 。
虽然这是一种有效且常用的代码类型 , 但链接器不知道MyAssembly、MyType和MyMethod是否在运行时实际使用 。 这可能会导致它们被剥离 , 进而导致运行时错误 。
使用依赖注入框架(如Zenject)或序列化库(如Newtonsoft)的开发人员必须意识到假阳性代码剥离是可能的 。 以下是一些最常见的解决方法:
链接器可以识别许多属性 , 并允许用户在无法识别它们时对依赖项进行注释 。 因此 , 用户可以添加属性不应被分离的程序集、类和方法 。
link.xml文件是一个针对每个项目的列表 , 记录了保留程序集、类型和其他代码 , 用户可以手动添加所需的程序集、类型和方法到link.xml , 或者使用UnityEditor APIgenerated additionallinkxmlfile在构建过程中生成link.xml文件 。
可寻址包也利用了LinkxmlGenerator 。 可寻址包的构建脚本会检查组中的资产列表 , 并将资产使用的类型添加到link.xml文件中 。 它还通过运行时的反射在内部添加了可寻址包使用的类型 。
Unity支持位于“资源”文件夹或其子文件夹中的多个link.xml文件 。 在构建过程中 , 链接器会合并和计算多个link.xml文件的条目 。
Unity 2020 LTS版中托管代码剥离有什么新功能
使用属性可能需要一些手动操作 。 但是如果项目已经在Unity 2020 LTS中 , 我们可以使用许多新的托管代码剥离注释属性来轻松、精确地在代码剥离过程中标记不该删除的程序集与类型 。 以下是一些方法:
Required AttributeUsagesAttribute:标记属性类型时 , 该类型的所有自定义属性也将被标记 , 从而减少在高剥离级别工作时的复杂性 。
RequireDerivedAttribute:标记类型时 , 从该类型派生的所有类型都将被标记 。