IL2CPP スクリプティングバックエンドは Unity プロジェクトにあるスクリプト、アセンブリからなる IL コードを C++ コードに変換します。C++ コードはその後プラットフォームのネイティブコンパイラを使用してコンパイルされます。ほとんどの場合スクリプティングバックエンドのことは気にしなくていいはずですが、IL2CPP には管理できる便利なオプションも用意されています。
IL2CPP スクリプティングバックエンドを使用する場合、il2cpp.exe がどのように C++ コードを生成するかを管理できます。特に C# アトリビュートは以下の実行時チェックを有効、無効に設定するのに使えます。
オプション | 詳細 | デフォルト値 |
---|---|---|
Null checks | このオプションが有効になっている場合、IL2CPP の生成する C++ コードは Null チェックを行い、必要に応じて NullReferenceException を投げます。このオプションが無効の場合、Null チェックは行われなくなります。プロジェクトによってはこのオプションを無効にすることにより実行時パフォーマンスが向上するものもあるかもしれません。しかし、生成されたコードにある Null な値への如何なるアクセスも保護されません。そのため不正な挙動の原因となる可能性があります。通常の場合 Null を参照した場合ゲームはすぐにクラッシュしますが、これを保証できなくなります。このオプションを外すと警告が出ます。 | 有効 |
Array bounds checks | このオプションを有効にしている場合、IL2CPP の生成した C++ コードは配列範囲チェックを行い、必要に応じて IndexOutOfRangeException の例外が発生します。このオプションが無効の場合、C++ のコードで配列範囲チェックは行われなくなります。プロジェクトによってはこのオプションを無効にすることで実行時パフォーマンスが向上するかもしれません。しかし、無効なインデックスを伴った配列への如何なるアクセスも保護されなくなります。それが原因で不定なメモリロケーションの読み取り、書き込みといった不正な挙動に繋がる可能性もあります。ほとんどの場合、これらのメモリアクセスは突発的な副作用を伴わず起こり、気づかない間にゲームの挙動がおかしくなることもありえます。このオプションを無効にする際は特別な注意を払ってください。 | 有効 |
Divide by zero checks | このオプションが有効になっていると、IL2CPP によって生成された C++ コードは整数の除算に対して 0 で割っていないかチェックを行い、必要に応じて管理された DivideByZeroException 例外を投げます。このオプションが無効になっていると、0 による除算チェックは整数の除算時に C++ コードで行われません。ほとんどのプロジェクトではこのオプションは無効にしてあるのが望ましいです。このチェックは実行時コストが高いため、有効にするのは必要な場合のみです。このオプションはデフォルトでは無効になっています。 | 無効 |
実行時チェックは Il2CppSetOptions 属性を使用することで C# コードから有効、無効のどちらかに設定することができます。この属性を使用するためにはまず Unity Editor をインストールしている場所を調べ、IL2CPP ディレクトリにある Il2CppSetOptionsAttribute.cs を見つけてください(Windows では Data\il2cpp に, OS X では Contents/Frameworks/il2cpp にあります)。このソースファイルをプロジェクトの Assets フォルダーにコピーしてください。属性は以下のように使えます。
[Il2CppSetOption(Option.NullChecks, false)]
public static string MethodWithNullChecksDisabled()
{
var tmp = new object();
return tmp.ToString();
}
Il2CppSetOptions 属性は型、メソッド、プロパティーに適用できます。ほとんどローカルスコープとして属性は使用されます。
[Il2CppSetOption(Option.NullChecks, false)]
public class TypeWithNullChecksDisabled
{
public static string AnyMethod()
{
// このメソッドで Null checks は無効になります
var tmp = new object();
return tmp.ToString();
}
[Il2CppSetOption(Option.NullChecks, true)]
public static string MethodWithNullChecksEnabled()
{
// このメソッドで Null checks は有効になります
var tmp = new object();
return tmp.ToString();
}
}
public class SomeType
{
[Il2CppSetOption(Option.NullChecks, false)]
public string PropertyWithNullChecksDisabled
{
get
{
// このメソッドで Null checks は無効になります.
var tmp = new object();
return tmp.ToString();
}
set
{
// このメソッドで Null checks は無効になります
value.ToString();
}
}
public string PropertyWithNullChecksDisabledOnGetterOnly
{
[Il2CppSetOption(Option.NullChecks, false)]
get
{
// このメソッドで Null checks は無効になります
var tmp = new object();
return tmp.ToString();
}
set
{
// このメソッドで Null checks は有効になります
value.ToString();
}
}
}