|
如果项目很大,代码量很多,不仅会使包体变大,编译时间变长,还会导致各种编译报错。比如:
ARM64 branch out of range (154869072 max is +/-128MB)
Unity提供了一种被称作托管代码剥离( managed code stripping )的方案用来删除未使用或无法访问的代码。托管代码剥离从托管程序集中删除代码,包括从项目中的 C# 脚本构建的程序集、作为包和插件一部分的程序集,以及 .NET Framework 中的程序集。
Unity 使用称为 Unity 链接器(Unity linker)的工具对项目程序集中的代码执行静态分析。静态分析识别在执行期间无法访问的任何类、类的部分、函数或函数的部分。此分析仅包括构建时存在的代码,因为在 Unity 执行静态分析时不存在运行时生成的代码。可以使用 **托管剥离级别 **来控制剥离的程度。
配置托管代码剥离:
配置托管代码剥离
转到编辑 > 项目设置 > 播放器。在其他设置中,找到优化一栏。将 Managed Stripping Level 属性设置为所需的值。
属性 | 功能 | Disabled | 不会移除任何代码。如果使用 mono ,这是默认设置 | Minimal | 只在 UnityEngine 和 .net 类库中搜索未使用的代码。不会删除任何用户编写的代码。此设置最不可能导致任何意外的运行时行为如果使用 IL2CPP ,这是默认设置。 | Low | Unity会搜索一些用户编写的程序集,以及所有 UnityEngine和 .net 类库来寻找未使用的代码。此设置应用一组规则,这些规则删除一些未使用的代码,但将意外后果的可能性降到最低,例如使用反射的运行时代码的行为更改。 | Medium | Unity 部分搜索所有程序集以查找无法访问的代码。此设置应用一组规则,这些规则剥离更多类型的代码模式以减少构建大小。尽管 Unity 不会删除所有可能无法访问的代码,但此设置确实会增加发生不良或意外行为更改的风险。 | High | Unity会对所有程序集进行广泛搜索,以找到无法访问的代码。在这个设置中,Unity优先考虑的是减少大小,而不是代码稳定性,并删除尽可能多的代码。这种搜索可能比较低的剥离级别花费更长的时间。彻底测试你的应用,仔细使用[Preserve]属性和link.xml文件,以确保Unity链接器不会剥离关键代码。 |
使用 托管代码剥离 需谨慎,防止必要的代码被剥离。我们可以使用 Preserve 或 Link.xml 来保护代码。
Preserve:
可以使用 Preserve 来防止 Unity 链接器剥离代码的特定部分。如果您的应用程序生成 Unity 执行静态分析时不存在的运行时代码,这将很有帮助;例如,通过反射。Preserve 要么为 Unity 链接器提供关于它不应该剥离哪些代码模式的一般指导,要么提供不剥离特定的、已定义的代码部分的指令。
例如:
class Foo{ [Preserve] public void PreservedMethod(){}}
Link.xml :
也可以在项目中包括一个名为 link.xml 的 .xml 文件,以保留特定程序集或程序集的一部分的列表。xml 文件必须存在于 Assets 文件夹或项目中的 Assets 文件夹的子目录中,并且文件中必须包含 <linker> 标记。Unity 链接器将保存在 link.xml 文件中的任何程序集、类型或成员视为根类型。
例如:
<linker> <!--Preserve types and members in an assembly--> <assembly fullname="AssemblyName"> <!--Preserve an entire type--> <type fullname="AssemblyName.MethodName" preserve="all"/> <!--No "preserve" attribute and no members specified means preserve all members--> <type fullname="AssemblyName.MethodName"/> <!--Preserve all fields on a type--> <type fullname="AssemblyName.MethodName" preserve="fields"/> <!--Preserve all fields on a type--> <type fullname="AssemblyName.MethodName" preserve="methods"/> <!--Preserve the type only--> <type fullname="AssemblyName.MethodName" preserve="nothing"/> <!--Preserving only specific members of a type--> <type fullname="AssemblyName.MethodName"> <!--Fields--> <field signature="System.Int32 FieldName" /> <!--Preserve a field by name rather than signature--> <field name="FieldName" /> <!--Methods--> <method signature="System.Void MethodName()" /> <!--Preserve a method with parameters--> <method signature="System.Void MethodName(System.Int32,System.String)" /> <!--Preserve a method by name rather than signature--> <method name="MethodName" /> <!--Properties--> <!--Preserve a property, it's backing field (if present), getter, and setter methods--> <property signature="System.Int32 PropertyName" /> <property signature="System.Int32 PropertyName" accessors="all" /> <!--Preserve a property, it's backing field (if present), and getter method--> <property signature="System.Int32 PropertyName" accessors="get" /> <!--Preserve a property, it's backing field (if present), and setter method--> <property signature="System.Int32 PropertyName" accessors="set" /> <!--Preserve a property by name rather than signature--> <property name="PropertyName" /> <!--Events--> <!--Preserve an event, it's backing field (if present), add, and remove methods--> <event signature="System.EventHandler EventName" /> <!--Preserve an event by name rather than signature--> <event name="EventName" /> </type> </assembly></linker>
详细请参考 Unity 官方文档:
https://docs.unity.cn/cn/current/Manual/ManagedCodeStripping.html
如果你做了托管代码剥离,但是在IOS还是会报ARM64 branch out of range,那么 你可以打开Xcode工程进行如下设置:
优化等级设为 -Os
把主工程和UnityFramework工程的优化等级都设为 -Os
<hr>
环境:
Unity:2021.3.2
Xcode:13.3.1 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|