Mono:这是 Unity 最初采用的方式,它将 C# 代码编译为中间语言 (IL),然后在目标平台上使用虚拟机 (VM) 将其转换为本地机器码执行。
IL2CPP:这是一种较新的方法,它会将 C# 代码先编译为 C++ 代码,再由 C++ 编译器生成针对特定平台优化后的二进制文件。这种方法通常能带来更好的性能,并且更容易集成到不同的操作系统中。
IL2CPP 提供了一些显著的优点,比如更高的运行效率和更小的应用体积。然而,它也有一些局限性,例如无法像 Mono 那样动态生成代码,这意味着你必须提前确定所有要用到的类型。如果某些类型是在运行时才决定使用的(例如通过反射或泛型),那么你需要采取特别措施来确保它们不会被裁剪掉。
1、调整剥离级别
在Unity的设置中,有一个叫做“Managed Stripping Level”的选项,可以选择不同的级别,控制IL2CPP的裁剪程度:
2、使用Link.xml文件
你可以通过在Unity项目中(或其任何子目录中)创建一个Link.xml
文件,告诉Unity哪些类型不能被删掉,确保它们在打包时不会被裁剪掉。
link.xml语法规则
<?xml version="1.0" encoding="UTF-8"?>
<!--保存整个程序集-->
<assembly fullname="UnityEngine" preserve="all"/>
<!--没有“preserve”属性,也没有指定类型意味着保留所有-->
<assembly fullname="UnityEngine"/>
<!--完全限定程序集名称-->
<assembly fullname="Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<type fullname="Assembly-CSharp.Foo" preserve="all"/>
</assembly>
<!--在程序集中保留类型和成员-->
<assembly fullname="Assembly-CSharp">
<!--保留整个类型-->
<type fullname="MyGame.A" preserve="all"/>
<!--没有“保留”属性,也没有指定成员 意味着保留所有成员-->
<type fullname="MyGame.B"/>
<!--保留类型上的所有字段-->
<type fullname="MyGame.C" preserve="fields"/>
<!--保留类型上的所有方法-->
<type fullname="MyGame.D" preserve="methods"/>
<!--只保留类型-->
<type fullname="MyGame.E" preserve="nothing"/>
<!--仅保留类型的特定成员-->
<type fullname="MyGame.F">
<!--类型和名称保留-->
<field signature="System.Int32 field1" />
<!--按名称而不是签名保留字段-->
<field name="field2" />
<!--方法-->
<method signature="System.Void Method1()" />
<!--保留带有参数的方法-->
<method signature="System.Void Method2(System.Int32,System.String)" />
<!--按名称保留方法-->
<method name="Method3" />
<!--属性-->
<!--保留属性-->
<property signature="System.Int32 Property1" />
<property signature="System.Int32 Property2" accessors="all" />
<!--保留属性、其支持字段(如果存在)和getter方法-->
<property signature="System.Int32 Property3" accessors="get" />
<!--保留属性、其支持字段(如果存在)和setter方法-->
<property signature="System.Int32 Property4" accessors="set" />
<!--按名称保留属性-->
<property name="Property5" />
<!--事件-->
<!--保存事件及其支持字段(如果存在),添加和删除方法-->
<event signature="System.EventHandler Event1" />
<!--根据名字保留事件-->
<event name="Event2" />
</type>
<!--泛型相关保留-->
<type fullname="MyGame.G`1">
<!--保留带有泛型的字段-->
<field signature="System.Collections.Generic.List`1<System.Int32> field1" />
<field signature="System.Collections.Generic.List`1<T> field2" />
<!--保留带有泛型的方法-->
<method signature="System.Void Method1(System.Collections.Generic.List`1<System.Int32>)" />
<!--保留带有泛型的事件-->
<event signature="System.EventHandler`1<System.EventArgs> Event1" />
</type>
<!--如果使用类型,则保留该类型的所有字段。如果类型不是用过的话会被移除-->
<type fullname="MyGame.I" preserve="fields" required="0"/>
<!--如果使用某个类型,则保留该类型的所有方法。如果未使用该类型,则会将其删除-->
<type fullname="MyGame.J" preserve="methods" required="0"/>
<!--保留命名空间中的所有类型-->
<type fullname="MyGame.SomeNamespace*" />
<!--保留名称中带有公共前缀的所有类型-->
<type fullname="Prefix*" />
</assembly>
</linker>
学习自:【unity进阶篇】unity如何实现跨平台及unity最优最小包体打包方式(.NET、Mono和IL2CPP知识介绍)-CSDN博客