Version: 2022.3
言語: 日本語
Mono 概要
IL2CPP 追加引数のためのプラットフォーム固有の設定

IL2CPP の概要

IL2CPP (Intermediate Language To C++) スクリプティングバックエンドは、Mono バックエンドの代替品です。IL2CPP は、広範なプラットフォームのアプリケーションに対し、優れたサポートを提供します。IL2CPP バックエンドは、MSIL (Microsoft Intermediate Language) コード (スクリプト内の C# コードなど) を C++ コードに変換し、その C++ コードを使って選択したプラットフォーム用のネイティブのバイナリファイル (.exe、.apk、.xap など) を作成します。

このような、Unity がネイティブバイナリをビルドする際に、特にターゲットプラットフォームに合わせたコードのコンパイルを、事前 (AOT、Ahead-of-Time) コンパイルと呼びます。一方、Mono のバックエンド は、実行時 (JIT) コンパイルと呼ばれる手法で、コードをランタイムにコンパイルします。

このページには以下の情報が含まれています。

AOT コンパイルをサポートしないプラットフォームもあります。そのため、IL2CPP バックエンドはすべてのプラットフォームで動作するわけではありません。また、AOT と IL2CPP をサポートしても、JIT コンパイルができないため、Mono バックエンドをサポートできないプラットフォームもあります。プラットフォームが両方のバックエンドをサポートする場合は、Mono がデフォルトとなります。詳細については、スクリプトの制限 を参照してください。

IL2CPP は、さまざまなプラットフォームのパフォーマンスを向上させることができますが、ビルドされたアプリケーションにマシンコードを置く必要があるため、ビルド時間と最終的にビルドされたアプリケーションのサイズの両方が増加します。詳細については、IL2CPP の仕組みとブログシリーズ An introduction to IL2CPP internals を参照してください。

IL2CPP は、Mono スクリプトバックエンドと同じ方法でマネージドコードのデバッグをサポートします。詳細は、Unity での C# コードのデバッグ を参照してください。

IL2CPP を使ったプロジェクトのビルド

IL2CPP を使ってプロジェクトをビルドするには、Unity のインストール時にバックエンドがインストールされる必要があります。Unity を最初にインストールするときに、必須でないモジュールとして IL2CPP を選択するか、Unity Hub を通じて既存のインストールに IL2CPP のサポートを加えることができます。詳細については、Unity Hub のインストール および Unity エディターへのモジュールの追加 を参照してください。

また、IL2CPP は C++ コードを生成するために、ターゲットプラットフォームのネイティブシステムを必要とします。つまり、特定のプラットフォームで IL2CPP を使用するには、そのプラットフォーム上でアプリケーションをビルドする必要があります。例えば、ビルドターゲットとして IL2CPP を MacOS で使用するには、MacOS を使用するマシンでアプリケーションをビルドする必要があります。各プラットフォームの IL2CPP 要件など、デスクトッププラットフォームのシステム要件の詳細については、Unity のシステム要件 のデスクトップのセクションを参照してください。

Unity がアプリケーションのビルドに使用するスクリプティングバックエンドを変更するには、次の 2 つの方法があります。

  • エディターの Player Settings メニューから。以下の手順で、Player Settings メニューからスクリプティングバックエンドを変更します。

    1. Edit > Project Settings の順に移動します。
    2. Player Settings ボタンをクリックし、 Inspector に表示された現在のプラットフォームの Player 設定を開きます。
    3. Other SettingsConfiguration セクションに移動します。
    4. Scripting Backend ドロップダウンをクリックして、IL2CPP を選択します。

    Player Settings メニューは、Build Settings メニューの中からも開くことができます。 File > Build Settings と移動し、Player Settings ボタンをクリックしてください。

  • エディターのスクリプティング API を通じて、PlayerSettings.SetScriptingBackend プロパティを使用して、Unity が使用するスクリプティングバックエンドを変更します。

Player の Configuration セクション
PlayerConfiguration セクション

ビルドプロセスを開始するには、Build Settings ウィンドウを開き、 Build ボタンをクリックします。その後、Unity は C# コードとアセンブリを C++ に変換し、最後にターゲットプラットフォーム用のバイナリファイルを生成します。

IL2CPP のしくみ

IL2CPP を使用してビルドを開始すると、Unity は自動的に以下の手順を実行します。

  1. Roslyn C# コンパイラーは、アプリケーションの C# コードと必要なすべてのパッケージコードを .NET DLL (マネージアセンブリ) にコンパイルします。
  2. Unity はマネージ バイトコードストリッピング を適用します。この手順により、ビルドされたアプリケーションのサイズを大幅に削減することができます。
  3. IL2CPP バックエンドは、すべてのマネージアセンブリを標準の C++ コードに変換します。
  4. C++ コンパイラーは、生成された C++ コードと IL2CPP のランタイム部分をネイティブのプラットフォームのコンパイラーでコンパイルします。
  5. そのコードをターゲットとするプラットフォームによって、実行ファイルか DLL のいずれかにリンクします。

IL2CPP と Mono 両方とも、スクリプトの属性で制御できる便利なオプションをいくつか提供します。詳細は、プラットフォーム依存コンパイル を参照してください。

IL2CPP は、Unity が特定のプラットフォーム用にコードを事前にコンパイルすることを可能にします。このプロセスの最後に Unity が生成するバイナリファイルには、ターゲットプラットフォームに必要なマシンコードがすでに含まれていますが、Mono はこのマシンコードをランタイムにコンパイルしなければなりません。AOT コンパイルは、ビルド時間を増加させますが、ターゲットプラットフォームとの互換性を高め、パフォーマンスを向上させることができます。

どちらのスクリプティングバックエンドも、ターゲットとするプラットフォームごとに新規にビルドする必要があります。例えば、Android と iOS の両方のプラットフォームをサポートするためには、アプリケーションを 2 回ビルドし、2 つのバイナリファイルを作成する必要があります。

アセンブリストリッピングステージでは、最終的なバイナリサイズを小さくすることができます。Unity は、最終的にビルドされるアプリケーションが使用しないバイトコードを削除します。

IL2CPP のビルド時間の最適化

IL2CPP を使用するプロジェクトのビルド時間は、Mono を使用する場合よりも大幅に長くなることがあります。しかし、ビルド時間を短縮するためにいくつか工夫できます。

マルウェア対策ソフトのスキャンからプロジェクトを除外する

プロジェクトをビルドする前に、Unity のプロジェクトフォルダーとターゲットのビルドフォルダーをマルウェア対策ソフトのスキャン対象から除外します。

プロジェクトとターゲットビルドフォルダーをソリッドステートドライブ (SSD) に保存する

Solid State Drive (SSD) は以前からあるハードディスクドライブ (HDD) に比べ、より速く読み込み、書き込みを行えます。IL コードを C++ に変換しそれをコンパイルすることは、大量の読み込み、書き込み操作を伴います。ストレージデバイスのスピードが速いと、この処理もより早くなります。

Build Settings の IL2CPP Code Generation オプションを変更する

IL2CPP のコード生成方法を変更するには、Build Settings を開いて IL2CPP Code Generation オプションを設定します。デフォルトでは、Faster runtime オプションが有効で、ランタイムに IL2CPP の影響を軽減するマシンコードがより多く生成されます。ビルド時間を短縮するには、このオプションを Faster (smaller) builds に設定します。この方法では、バイナリ実行ファイルに生成されるマシンコードが少なくなるため、ランタイムのパフォーマンスが低下する可能性がありますが、ビルド時間とバイナリサイズが大幅に削減されます。

Il2CppSetOption を使用したランタイムチェックの使用

IL2CPP スクリプティングバックエンドを使用すると、il2cpp.exe が C++ コードを生成する方法を制御できます。Il2CppSetOption 属性を使用して、以下のランタイムチェックを有効または無効にすることができます。

プロパティ 説明 デフォルト
Null checks このオプションを有効にすると、IL2CPP が生成する C++ コードにはに null チェックが加えられ、必要に応じてマネージ NullReferenceException 例外が投げられます。このオプションを無効にすると、生成された C++ コードに null チェックを加えません。

この設定を無効にすると、Unity が生成されたコードの null 値にアクセスしようとするのを防げないため、誤った動作の原因になる可能性があります。Unity では、このオプションを無効にしないことを推奨します。
有効
Array bounds checks このオプションを有効にすると、IL2CPP が生成する C++ コードには配列の境界チェックが加えられ、必要に応じてマネージ IndexOutOfRangeException 例外がスローされます。このオプションを無効にすると、IL2CPP は生成される C++ コードに配列の境界チェックを生成しません。

プロジェクトによっては、このオプションを無効にすることでランタイムパフォーマンスが向上する場合があります。ただし、このオプションを無効にすると、生成されたコード内で無効なインデックスを持つ配列にアクセスしようとする試みが阻止されないため、任意のメモリ位置からの読み取りまたは任意のメモリへの書き込みなど、不正な動作が発生する可能性があります。ほとんどの場合、このようなメモリアクセスは直ちに悪影響を生じることなく発生し、明らかな警告がないままアプリケーションの状態を破壊することがあります。このため、これらのエラーのデバッグは非常に困難になります。Unityでは、このオプションを有効にしておくことを推奨します。
有効
Divide by zero checks このオプションを有効にすると、IL2CPP によって生成される C++ コードには、整数のゼロ除算チェックが加えられ、必要に応じて管理された DivideByZeroException 例外を投げます。このオプションを無効にすると、IL2CPP は生成される C++ コードに整数のゼロ除算チェックを加えません。

これらのチェックは、実行時のパフォーマンスに影響を与えます。このオプションは、ゼロ除算チェックを実行する必要がある場合にのみ有効にし、そうでない場合は無効のままにしてください。
無効

Il2CppSetOptions 属性を使用する手順は以下の通りです。

  1. Unity バージョンがインストールされているディレクトリで、Windows の場合は 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 は null チェックを行いません
        var tmp = new object();
        return tmp.ToString();
    }

    [Il2CppSetOption(Option.NullChecks, true)]
    public static string MethodWithNullChecksEnabled()
    {
        // このメソッドでは、Unity は null チェックを行います
        var tmp = new object();
        return tmp.ToString();
    }
}

public class SomeType
{
    [Il2CppSetOption(Option.NullChecks, false)]
    public string PropertyWithNullChecksDisabled
    {
        get
        {
            // ここでは、Unity は null チェックを行いません
            var tmp = new object();
            return tmp.ToString();
        }
        set
        {
            // ここでは、Unity は null チェックを行いません
            value.ToString();
        }
    }

    public string PropertyWithNullChecksDisabledOnGetterOnly
    {
        [Il2CppSetOption(Option.NullChecks, false)]
        get
        {
            // ここでは、Unity は null チェックを行いません
            var tmp = new object();
            return tmp.ToString();
        }
        set
        {
            // ここでは、Unity は null チェックを行います
            value.ToString();
        }
    }
}

•2018–05–15 修正されたページ

Mono 概要
IL2CPP 追加引数のためのプラットフォーム固有の設定