版本:2022.3
语言:英语
Mono 概述
处理 IL2CPP 额外参数的平台特定设置

IL2CPP 概述

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

要使用 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 菜单更改脚本后端,请执行以下步骤

    1. 转到 编辑 > 项目设置
    2. 单击 Player Settings 按钮以打开当前平台的 Player 设置(在 检查器 中)。
    3. 其他设置 子菜单下的 配置 部分标题。
    4. 单击 Scripting Backend 下拉菜单,然后选择 IL2CPP

    您还可以在 Build Settings 菜单内部打开 Player Settings 菜单;转到 文件 > 构建设置 并单击 Player Settings 按钮。

  • 通过 Editor 脚本 API。使用 PlayerSettings.SetScriptingBackend 属性更改Unity使用的脚本后端。

The Configuration section of the Player settings
Player 设置的 配置 部分

要开始构建过程,打开 构建设置 窗口并单击 构建 按钮。然后Unity将您的 C# 代码和程序集转换为 C++,最后生成目标平台上的二进制文件。

IL2CPP如何工作

当您使用 IL2CPP 开始构建时,Unity将自动执行以下步骤

  1. Roslyn C# 编译器将您的应用程序的 C# 代码和任何必需的包代码编译为 .NET DLL(受管理程序集)。
  2. Unity应用托管的 字节码剥离。此步骤可以显着减少构建应用程序的大小。
  3. IL2CPP 后端将所有托管程序集转换为标准 C++ 代码。
  4. C++ 编译器使用本地平台编译器编译生成的 C++ 代码和IL2CPP的运行时部分。
  5. 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 不会阻止在生成的代码中尝试访问空值,这可能会导致不正确的行为。您的应用程序可能在解除对空值的引用后不久崩溃。Unity 建议不要禁用此选项。
启用
数组边界检查 如果此选项启用,IL2CPP 生成的 C++ 代码将包含数组边界检查,并在必要时抛出托管 IndexOutOfRangeException 异常。如果此选项禁用,IL2CPP 不会将数组边界检查输出到生成的 C++ 代码中。

对于某些项目,禁用此选项可能会提高运行时的性能。但是,当此选项禁用时,Unity 不会阻止在生成的代码中尝试访问具有无效索引的数组,这可能导致不正确的行为,包括从任意内存位置读取或写入。在大多数情况下,这些内存访问不会产生任何立即的副作用,并且可能在没有任何明显的警告迹象的情况下破坏应用程序的状态。这使得调试这些错误变得极其困难。Unity 建议您启用此选项。
启用
除以零检查 如果此选项启用,IL2CPP 生成的 C++ 代码将在整除中包含除以零检查,并在必要时抛出托管 DivideByZeroException 异常。如果此选项禁用,IL2CPP 不会在生成的 C++ 代码中进行除以零检查。

这些检查会影响到运行时的性能。仅在需要运行除以零检查时启用此选项;否则请保持禁用。
禁用

使用 Il2CppSetOption 属性

  1. 在 Windows 上,在您的 Unity 版本安装目录中,导航到 Data\il2cpp 目录,或在 OS X 上导航到 Contents/Frameworks/il2cpp 目录。
  2. 找到 Il2CppSetOptionAttribute.cs 源文件。
  3. 将源文件复制到您的项目 Assets 目录中。

以下示例说明了如何使用 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 页面修改

Mono 概述
处理 IL2CPP 额外参数的平台特定设置