Unity3D :IL2CPP概述
推荐:将NSDT场景编辑器加入你的3D工具链
3D工具集:NSDT简石数字孪生
IL2CPP概述
IL2CPP(中间语言到C++)脚本后端是Mono后端的替代方案。IL2CPP 为跨更多平台的应用程序提供更好的支持。IL2CPP 后端将 MSIL(Microsoft 中间语言)代码(例如,脚本中的 C# 代码)转换为C++代码,然后使用该C++代码为所选平台创建本机二进制文件(例如,.exe、.apk 或 .xap)。
这种类型的编译称为提前 (AOT) 编译,其中 Unity 在构建本机二进制文件时专门为目标平台编译代码。Mono 后端使用一种称为实时编译 (JIT) 的技术在运行时编译代码。
在此页面上:
- 使用 IL2CPP 构建项目
- IL2CPP 的工作原理
- 优化 IL2CPP 构建时间
- 使用 IL2CppSetOption 启用运行时检查
某些平台不支持 AOT 编译,因此 IL2CPP 后端并非在每个平台上都有效。其他平台支持 AOT 和 IL2CPP,但不允许 JIT 编译,因此不能支持 Mono 后端。当平台可以同时支持两个后端时,Mono 是默认的。有关详细信息,请参阅脚本限制。
IL2CPP 可以提高各种平台的性能,但是在构建的应用程序中包含机器代码的需求会增加构建时间和最终构建应用程序的大小。有关详细信息,请参阅 IL2CPP 的工作原理和博客系列 IL2CPP 内部简介。
IL2CPP 支持托管代码的调试,方式与 Mono 脚本后端相同。有关更多信息,请参见在 Unity 中调试 C# 代码。
使用 IL2CPP 构建项目
要使用 IL2CPP 构建项目,您需要在 Unity 安装中安装后端。首次安装 Unity 版本时,可以选择 IL2CPP 作为可选模块,或通过 Unity Hub 将 IL2CPP 支持添加到现有安装中。有关更多信息,请参见安装 Unity 中心和将模块添加到 Unity 编辑器。
您可以通过以下两种方式之一更改 Unity 用于构建应用程序的脚本后端:
通过编辑器中的播放器设置菜单。执行以下步骤,通过“播放器设置”菜单更改脚本后端:
- 转到编辑>项目设置。
- 单击“播放器设置”按钮,在检查器中打开当前平台的“播放器”设置。
- 导航到“其他设置”子菜单下的“配置”部分标题。
- 单击脚本后端下拉菜单,然后选择 IL2CPP。您也可以从“构建设置”菜单中打开“播放器设置”菜单;转到文件>构建设置,然后单击播放器设置按钮。
- 通过编辑器脚本 API。使用 PlayerSettings.SetScriptingBackend 属性更改 Unity 使用的脚本后端。

要开始构建过程,请打开“构建设置”窗口,然后单击“构建”按钮。然后,Unity 将 C# 代码和程序集转换为C++,并最终为目标平台生成二进制文件。
IL2CPP 的工作原理
使用 IL2CPP 开始构建时,Unity 会自动执行以下步骤:
- Roslyn C# 编译器将应用程序的 C# 代码和任何所需的包代码编译为 .NET DLL(托管程序集)。
- Unity 应用托管字节码剥离。此步骤可以显著减小生成的应用程序的大小。
- IL2CPP 后端将所有托管程序集转换为标准C++代码。
- C++编译器使用本机平台编译器编译生成的C++代码和 IL2CPP 的运行时部分。
- Unity 会创建可执行文件或 DLL,具体取决于您的目标平台。
IL2CPP 和 Mono 都提供了一些有用的选项,您可以使用脚本中的属性来控制这些选项。有关详细信息,请参阅依赖于平台的编译。
IL2CPP 使 Unity 能够针对特定平台预编译代码。Unity 在此过程结束时生成的二进制文件已经包含目标平台所需的机器代码,而 Mono 必须在执行期间在运行时编译此机器代码。AOT 编译确实会增加生成时间,但它也提高了与目标平台的兼容性,并且可以提高性能。
这两个脚本后端都需要针对要面向的每个平台进行新的构建。例如,要同时支持 Android 和 iOS 平台,您需要构建应用程序两次并生成两个二进制文件。
组件剥离阶段有助于减小最终的二进制大小。Unity 会删除最终构建的应用程序不使用的任何字节码。
优化 IL2CPP 构建时间
使用 IL2CPP 时的项目构建时间可能比使用 Mono 时长得多。但是,您可以执行多项操作来减少生成时间。
从反恶意软件扫描中排除您的项目
在构建项目之前,您可以从反恶意软件扫描中排除 Unity 项目文件夹和目标构建文件夹。
将项目和目标生成文件夹存储在固态驱动器 (SSD) 上
固态硬盘 (SSD) 的读/写速度比传统硬盘驱动器 (HDD) 更快。将 IL 代码转换为 C++ 并对其进行编译涉及大量读/写操作,因此更快的存储设备可以加快此过程。
更改“生成设置”中的“IL2CPP 代码生成”选项
若要更改 IL2CPP 生成代码的方式,请打开“生成设置”并配置 IL2CPP 代码生成选项 默认情况下,启用“更快的运行时”选项,这将生成更多机器代码,从而减少 IL2CPP 在运行时的影响。若要缩短生成时间,可以将此选项设置为“更快(更小)的生成”。此方法在二进制可执行文件中生成并包含较少的机器代码,因此可以降低运行时的性能,但也大大减少了构建时间和二进制大小。
使用 Il2CppSetOption 启用运行时检查
使用 IL2CPP 脚本后端时,可以控制 il2cpp.exe 生成C++代码的方式。可以使用 Il2CppSetOption 属性来启用或禁用以下运行时检查:
属性: | 描述: | 违约: |
---|---|---|
空检查 | 如果启用此选项,IL2CPP 生成的C++代码将包含空检查,并根据需要引发托管的 NullReferenceException 异常。如果禁用此选项,IL2CPP 不会在生成的C++代码中发出空检查。对于某些项目,禁用此选项可能会提高运行时性能。 禁用此设置后,Unity 不会阻止尝试访问生成的代码中的空值,这可能会导致不正确的行为。应用程序可能会在取消引用 null 值后不久崩溃。Unity 建议您不要禁用此选项。 | 启用 |
数组边界检查 | 如果启用此选项,IL2CPP 生成的C++代码将包含数组边界检查,并根据需要引发托管的 IndexOutOfRangeException 异常。如果禁用此选项,IL2CPP 不会将数组边界检查发出到生成的C++代码中。 对于某些项目,禁用此选项可能会提高运行时性能。但是,禁用此选项后,Unity 不会阻止尝试访问生成的代码中具有无效索引的数组,这可能会导致不正确的行为,包括读取或写入任意内存位置。在大多数情况下,这些内存访问不会立即产生任何副作用,并且可能会损坏应用程序的状态,而没有明显的警告标志。这会使调试这些错误变得极其困难。Unity 建议您保持启用此选项。 | 启用 |
除以零检查 | 如果启用此选项,IL2CPP 生成的代码C++包含整数除法的除以零检查,并根据需要引发托管的除以零异常异常。如果禁用此选项,IL2CPP 不会在整数除法时发出零除检查到生成的C++代码中。 这些检查会影响运行时的性能。仅当需要运行除以零检查时,才应启用此选项;否则,请将其禁用。 | 禁用 |
要使用 Il2CppSetOption 属性,请执行以下操作:
- 在安装 Unity 版本的目录中,导航到 Windows 上的 Data\il2cpp 目录或 OS X 上的 Content/Frameworks/il2cpp 目录。
- 找到 Il2CppSetOptionAttribute.cs源文件。
- 将源文件复制到项目的资产目录中。
下面的示例介绍如何使用 Il2CppSetOption 属性:
[Il2CppSetOption(Option.NullChecks, false)]
public static string MethodWithNullChecksDisabled()
{
var tmp = new object();
return tmp.ToString();
}
可以将 Il2CppSetOption 属性应用于类型、方法和属性。Unity 使用最本地范围内的属性。
[Il2CppSetOption(Option.NullChecks, false)]
public class TypeWithNullChecksDisabled
{
public static string AnyMethod()
{
// Unity doesn’t perform null checks in this method.
var tmp = new object();
return tmp.ToString();
}
[Il2CppSetOption(Option.NullChecks, true)]
public static string MethodWithNullChecksEnabled()
{
// Unity performs null checks in this method.
var tmp = new object();
return tmp.ToString();
}
}
public class SomeType
{
[Il2CppSetOption(Option.NullChecks, false)]
public string PropertyWithNullChecksDisabled
{
get
{
// Unity doesn’t perform null checks here.
var tmp = new object();
return tmp.ToString();
}
set
{
// Unity doesn’t perform null checks here.
value.ToString();
}
}
public string PropertyWithNullChecksDisabledOnGetterOnly
{
[Il2CppSetOption(Option.NullChecks, false)]
get
{
// Unity doesn’t perform null checks here.
var tmp = new object();
return tmp.ToString();
}
set
{
// Unity performs null checks here.
value.ToString();
}
}
}
由3D建模学习工作室整理翻译,转载请注明出处!