IL2CPP(中间语言到 C++ 脚本后端驱动 Unity 脚本的高级框架。Unity 支持三种不同的脚本后端,具体取决于目标平台:Mono、.NET 和 IL2CPP。但是,通用 Windows 平台仅支持其中两种:.NET 和 IL2CPP。更多信息
参考术语表 是 Mono 后端的替代方案。IL2CPP 为更广泛平台上的应用程序提供了更好的支持。IL2CPP 后端将 MSIL(微软中间语言)代码(例如,脚本中的 C# 代码)转换为 C++ 代码,然后使用此 C++ 代码为所选平台创建本机二进制文件(例如,.exe、.apk 或 .xap)。
在 Unity 生成本机二进制文件时,Unity 会专门针对目标平台编译代码,这种类型的编译称为预编译(AOT)。Mono 后端 使用即时编译(JIT)技术编译代码。
本页内容
一些平台不支持 AOT 编译AOT(提前编译)编译是一种优化方法,所有平台(iOS 除外)都用于优化构建的播放器的尺寸。更多信息
参考术语表,因此 IL2CPP 后端 并不在所有平台上工作。其他平台支持 AOT 和 IL2CPP,但禁止 JIT 编译,因此无法支持 Mono 后端。当平台可以支持两种后端时,Mono 是默认选择。有关更多信息,请参阅脚本限制。
IL2CPP 可以在多种平台上提升性能,但需要在构建的应用程序中包含机器代码,这将增加构建时间和最终构建应用的大小。有关更多信息,请参阅IL2CPP 内部介绍。
IL2CPP 支持以与 Mono 脚本后端相同的方式调试托管代码。有关更多信息,请参阅Unity 中调试 C# 代码。
要使用 IL2CPP 构建 Project,您需要将其安装在与 Unity 安装中。您可以在安装 Unity 版本时将 IL2CPP 作为可选模块选择,或通过 Unity Hub 向现有安装添加 IL2CPP 支持。有关更多信息,请参阅安装 Unity Hub 和将模块添加到 Unity 编辑器。
IL2CPP 还需要目标平台特有的系统来生成 C++ 代码。这意味着为了在特定平台上使用 IL2CPP,您需要在该平台上构建应用程序。例如,若要在以 MacOS 为构建目标时使用 IL2CPP,您需要在一台使用 MacOS 的机器上构建应用程序。有关桌面平台的系统要求,包括 IL2CPP 对各个平台的要求,请参阅Unity 系统要求中的桌面部分。
您可以通过两种方式更改Unity用于构建您的应用程序的脚本后端
通过编辑器的 Player Settings允许您为Unity构建的最终游戏设置各种玩家特定选项的设置。 更多信息
在 术语表 中查看 菜单。要通过 Player Settings 菜单更改脚本后端,请执行以下步骤
您还可以在 Build Settings 菜单内部打开 Player Settings 菜单;转到 文件 > 构建设置 并单击 Player Settings 按钮。
通过 Editor 脚本 API。使用 PlayerSettings.SetScriptingBackend 属性更改Unity使用的脚本后端。
要开始构建过程,打开 构建设置 窗口并单击 构建 按钮。然后Unity将您的 C# 代码和程序集转换为 C++,最后生成目标平台上的二进制文件。
当您使用 IL2CPP 开始构建时,Unity将自动执行以下步骤
IL2CPP 和 Mono 都提供了一些有用的选项,您可以通过脚本中的属性来控制( 脚本一段代码,允许您创建自己的组件、触发游戏事件、随时间修改组件属性,以及以任何方式响应用户输入。 更多信息
在 术语表 中查看)。有关更多信息,请参阅 平台相关编译。
IL2CPP 允许Unity针对特定平台预编译代码。Unity在此过程结束时生成的二进制文件已包含目标平台的必要机器代码,而Mono必须在运行时执行此机器代码的编译。AOT编译会增加构建时间,但它还可以提高目标平台的兼容性并提高性能。
每个脚本后端都需要为每个要目标平台构建新的生成。例如,为了支持 Android 和 iOS 平台,您需要构建应用程序两次并生成两个二进制文件。
程序集剥离阶段有助于减小最终二进制文件大小。Unity删除了最终构建的应用程序不使用的任何字节码。
使用 IL2CPP 的项目构建时间可能比使用 Mono 时长得多。然而,您可以通过做几件事来减少构建时间。
从反恶意软件软件扫描中排除您的项目
您可以在构建项目之前,将Unity项目文件夹和目标构建文件夹从反恶意软件软件扫描中排除。
将项目和目标构建文件夹存储在固态硬盘(SSD)上
固态硬盘(SSD)相比传统硬盘驱动器(HDD)具有更快的读写速度。将 IL 代码转换为 C++ 并编译涉及大量的读写操作,因此较快的存储设备可以加快此过程。
在构建设置中更改 IL2CPP 代码生成选项
要更改 IL2CPP 生成代码的方式,请打开构建设置并配置 IL2CPP 代码生成选项。默认情况下,启用了“更快的运行时”选项,这会产生更多的机器代码,以减少 IL2CPP 在运行时的负面影响。为了减少构建时间,可以将此选项设置为“更快的(更小的)构建”。这种方法在二进制可执行文件中生成和包含较少的机器代码,因此在运行时可以降低性能,但也可以显著减少构建时间和二进制文件大小。
当您使用 IL2CPP 脚本后端时,可以控制 il2cpp.exe 生成 C++ 代码的方式。您可以使用 Il2CppSetOption 属性启用或禁用以下运行时检查
属性 | 描述 | 默认值 |
---|---|---|
空检查 | 如果此选项启用,IL2CPP 生成的 C++ 代码将包含空检查,并在必要时抛出托管 NullReferenceException 异常。如果此选项禁用,IL2CPP 不会将空检查输出到生成的 C++ 代码中。对于某些项目,禁用此选项可能会改进运行时的性能。 当此设置禁用时,Unity 不会阻止在生成的代码中尝试访问空值,这可能会导致不正确的行为。您的应用程序可能在解除对空值的引用后不久崩溃。Unity 建议不要禁用此选项。 |
启用 |
数组边界检查 | 如果此选项启用,IL2CPP 生成的 C++ 代码将包含数组边界检查,并在必要时抛出托管 IndexOutOfRangeException 异常。如果此选项禁用,IL2CPP 不会将数组边界检查输出到生成的 C++ 代码中。 对于某些项目,禁用此选项可能会提高运行时的性能。但是,当此选项禁用时,Unity 不会阻止在生成的代码中尝试访问具有无效索引的数组,这可能导致不正确的行为,包括从任意内存位置读取或写入。在大多数情况下,这些内存访问不会产生任何立即的副作用,并且可能在没有任何明显的警告迹象的情况下破坏应用程序的状态。这使得调试这些错误变得极其困难。Unity 建议您启用此选项。 |
启用 |
除以零检查 | 如果此选项启用,IL2CPP 生成的 C++ 代码将在整除中包含除以零检查,并在必要时抛出托管 DivideByZeroException 异常。如果此选项禁用,IL2CPP 不会在生成的 C++ 代码中进行除以零检查。 这些检查会影响到运行时的性能。仅在需要运行除以零检查时启用此选项;否则请保持禁用。 |
禁用 |
使用 Il2CppSetOption 属性
以下示例说明了如何使用 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();
}
}
}
• 2018–05–15 页面修改