Version: 2023.2
言語: 日本語
IL2CPP によるマネージスタックトレース
マネージコードストリッピング

スクリプトの制限

Unity は、サポートしているすべてのプラットフォームで共通のスクリプティング API と体験を提供します。ただし、独自の制限があるプラットフォームもあります。これらの制限を理解するために、以下の表では、各プラットフォームとスクリプティングバックエンドに適用される制限について説明します。

プラットフォーム (スクリプティングバックエンド) 事前 (AOT) コンパイル Supports threads
Android (IL2CPP) あり あり
Android (Mono) なし あり
iOS (IL2CPP) あり あり
スタンドアロン (IL2CPP) あり あり
スタンドアロン (Mono) なし あり
ユニバーサル Windows プラットフォーム (IL2CPP) あり あり
WebGL (IL2CPP) あり なし

Ahead-of-time compile (AOT)

プラットフォームの中には、ランタイムのコード生成ができないものもあります。そのため、そのようなデバイスで実行時 (Just-In-Time、JIT) コンパイルをおこなうと失敗します。代わりに、すべてのコードを事前 (Ahead-Of-Time、AOT) にコンパイルする必要があります。しばしば、この差異はあまり重要でないこともあります。しかし、ある特定の場合では、AOT コンパイルを必要とするプラットフォームには、追加の配慮が必要なことがあります。

Reflection

Reflection is supported on AOT platforms. However if this compiler cannot infer that the code is used via reflection the code may not exist at runtime. See [[wiki:ManagedCodeStripping|Managed Code Stripping]] for more information.

System.Reflection.Emit

An AOT platform cannot implement any of the methods in the System.Reflection.Emit namespace.

シリアライズ

事前 (AOT) コンパイルが必要なプラットフォームでは、リフレクションの使用が原因でシリアライズと非シリアライズで問題が発生することがあります。シリアライズと非シリアライズの一部として、型とメソッドをリフレクション経由でのみ使用できる場合、事前コンパイラーは型とメソッドのためにコードが生成される必要があることを検知することができません。

Generic Types and Methods

For generic types and methods the compiler must determine which generic instances are used because different generic instances may require different code. For example the code for List<int> is different than it is for List<double>. However IL2CPP will share code for usages for reference types, so the same code will be used for List<object> and List<string>.

It is possible to reference generic types and methods that IL2CPP did not find a compile time in the following cases:

  1. Creating a new generic instance at runtime: Activator.CreateInstance(typeof(SomeGenericType<>).MakeGenericType(someType));
  2. Invoking a static method on a generic instance: typeof(SomeGenericType<>).MakeGenericType(someType)).GetMethod("AMethod").Invoke(null, null);
  3. Invoking a static generic method: typeof(SomeType).GetMethod("GenericMethod").MakeGenericMethod(someType).Invoke(null, null);
  4. Some calls to generic virtual functions that cannot be inferred at compile time.
  5. Calls with deeply nested generic value types. e.g. Struct<Struct<Struct<...<Struct<int>>>>.

To support those cases IL2CPP generates generic code that will work with any type parameter. However this code is slower because it can make no assumptions on the size of the type or if it is a reference or value type. If you need to ensure that faster generic methods are generated you do the following: * If the generic argument will always be a reference type, add the where: class constraint. Then IL2CPP will generate the fallback method using reference type sharing which causes no performance degradation. * If the generic argument will always be a value type, add the where: struct constraint. This enables some optimizations, but since the value types can be different sizes the code will still be slower. * Create a method named UsedOnlyForAOTCodeGeneration and add references to the generic types and methods you wish IL2CPP to generate. This method does not need (and probably shouldn’t) be called. The example below will ensure that a specialization for GenericType<MyStruct> will be generated.

public void UsedOnlyForAOTCodeGeneration()
{
    // Ensure that IL2CPP will create code for MyGenericStruct
    // using MyStruct as an argument.
    new GenericType<MyStruct>();

    // Ensure that IL2CPP will create code for SomeType.GenericMethod
    // using MyStruct as an argument.
    new SomeType().GenericMethod<MyStruct>();

    public void OnMessage<T>(T value) 
    {
        Debug.LogFormat("Message value: {0}", value);
    }

    // Include an exception so we can be sure to know if this
    // method is ever called.
    throw new InvalidOperationException(
        "This method is used for AOT code generation only. " +
        "Do not call it at runtime.");
}

Note that when the “Faster (smaller) builds” setting is enabled only the single fully sharable version of generic code is compiled. This reduces the number of methods generated, reducing compile time and build size, but comes at the expense of runtime performance.

ネイティブコードからのマネージメソッドの呼び出し

ネイティブコードから呼び出せるように C 言語の関数ポインターにマーシャリングを行う必要があるマネージメソッドには、AOT プラットフォーム上でいくつかの制限があります。

  • マネージメソッドは静的メソッドでなければなりません。
  • マネージメソッドは、MonoPInvokeCallback 属性を持つ必要があります。
  • If the managed method is generic the [MonoPInvokeCallback(Type)] overload may be need to be used to specify the generic specializations that need to be supported. If so the type must be a generic instance with the correct number of generic arguments. It is possible to have multiple [MonoPInvokeCallback] attributes on a method as below:
// Generates reverse P/Invoke wrappers for NameOf<long> and NameOf<int>
// Note that the types are only used to indicate the generic arguments.
[MonoPInvokeCallback(typeof(Action<long>))]
[MonoPInvokeCallback(typeof(Action<int>))]
private static string NameOfT<T>(T item) 
{
    return typeof(T).Name;
}

スレッド不可

プラットフォームによっては、スレッドの使用をサポートしていません。そのため、System.Threading 名前空間を使用するマネージコードはすべて、ランタイムに失敗します。また、.NET クラスライブラリの一部は、暗示的にスレッドに依存しています。よく使われる例としては、System.Timers.Timer クラスがあり、スレッドのサポートに依存しています。

例外フィルター

IL2CPP supports exception filters, however the execution order filter statements and catch blocks is different because IL2CPP uses C++ exceptions to implement managed exceptions. This will not be noticeable unless a filter blocks writes to a field.

MarshalAs と FieldOffset 属性

IL2CPP は、MarhsalAsFieldOffset 属性をランタイムで反映することをサポートしていません。IL2CPP はコンパイル時にはこれらの属性をサポートしています。適切な プラットフォーム呼び出しによるマーシャリング を行うために、これらを使用する必要があります。

dynamic キーワード

IL2CPPは、C# の dynamic キーワードには対応していません。このキーワードには JIT コンパイルが必要ですが、IL2CPP では不可能です。

Marshal.Prelink

IL2CPPは、 Marshal.Prelink または Marshal.PrelinkAll APIメソッドをサポートしていません。

System.Diagnostics.Process API

IL2CPP doesn’t support the System.Diagnostics.Process API methods. For cases where this is required on desktop platforms, use the Mono scripting backend.

IL2CPP によるマネージスタックトレース
マネージコードストリッピング
Copyright © 2023 Unity Technologies
优美缔软件(上海)有限公司 版权所有
"Unity"、Unity 徽标及其他 Unity 商标是 Unity Technologies 或其附属机构在美国及其他地区的商标或注册商标。其他名称或品牌是其各自所有者的商标。
公安部备案号:
31010902002961