Unityでは、サポートしているすべてのプラットフォームで、同じ API が使用できるように努力しています。ですが、いくつかのプラットフォームでは、固有の制限があります。これらの制限を理解して、クロスプラットフォームのコードが書けるようになるために、以下に各プラットフォームに適用される制限とスクリプティングバックエンドについて説明します。
プラットフォーム (スクリプトバックエンド) | 事前コンパイル | スレッドなし | .NET Core クラスライブラリサブセット | |
---|---|---|---|---|
Android (IL2CPP) | ✔ | |||
Android (Mono) | ||||
iOS (IL2CPP) | ✔ | |||
PlayStation 4 (IL2CPP) | ✔ | |||
PlayStation Vita (IL2CPP) | ✔ | |||
スタンドアロン (IL2CPP) | ✔ | |||
スタンドアロン (Mono) | ||||
Switch (IL2CPP) | ✔ | |||
ユニバーサル Windows プラットフォーム (IL2CPP) | ✔ | |||
ユニバーサル Windows プラットフォーム (.NET) | ✔ | |||
WebGL (IL2CPP) | ✔ | ✔ | ||
WiiU (Mono) | ||||
XBox One (IL2CPP) | ✔ |
注意 :この機能は非推奨であるため、使用しないでください。 .NET 4を使用してください。
プラットフォーム (スクリプトバックエンド) | 事前コンパイル | スレッドなし | .NET Core クラスライブラリサブセット | |
---|---|---|---|---|
Android (IL2CPP) | ✔ | |||
Android (Mono) | ||||
iOS (IL2CPP) | ✔ | |||
PlayStation 4 (IL2CPP) | ✔ | |||
PlayStation 4 (Mono) | ✔ | |||
PlayStation Vita (IL2CPP) | ✔ | |||
PlayStation Vita (Mono) | ✔ | |||
スタンドアロン (IL2CPP) | ✔ | |||
スタンドアロン (Mono) | ||||
Switch (IL2CPP) | ✔ | |||
ユニバーサル Windows プラットフォーム (IL2CPP) | ✔ | |||
ユニバーサル Windows プラットフォーム (.NET) | ✔ | |||
WebGL (IL2CPP) | ✔ | ✔ | ||
WiiU (Mono) | ||||
XBox One (IL2CPP) | ✔ | |||
XBox One (Mono) | ✔ |
プラットフォームの中には、実行時のコード生成ができないものもあります。そのため、そのようなデバイスで実行時 (Just-In-Time、JIT) コンパイルをおこなうと失敗します。代わりに、すべてのコードを事前 (Ahead-Of-Time、AOT) にコンパイルする必要があります。しばしば、この差異はあまり重要でないこともあります。しかし、ある特定の場合では、AOT コンパイルを必要とするプラットフォームには、追加の配慮が必要なことがあります。
事前 (AOT) コンパイルが必要なプラットフォームには、System.Reflection.Emit 名前空間のメソッドを実装することができません。それ以外の System.Reflection は、使用可能なことに気を付けてください。ただし、リフレクションを通して使用されるコードが実行時に必要であることをコンパイラーが検知する必要があります。
事前 (AOT) コンパイルが必要なプラットフォームでは、リフレクションの使用が原因でシリアライズと非シリアライズで問題が発生することがあります。シリアライズと非シリアライズの一部として、型とメソッドをリフレクション経由でのみ使用できる場合、事前コンパイラーは型とメソッドのためにコードが生成される必要があることを検知することができません。
ジェネリックメソッドでは、開発者が書いたコードを拡張して、デバイスで実際に実行できるようなコードにするコンパイラーによる追加作業が必要です。例えば、int と doubleをもつListでは、異なるコードが必要です。仮想メソッドが存在する場合、挙動はコンパイル時よりもはむしろ実行時に決定されます。そのため、ソースコードから明白にされないコードがある場合、コンパイラーによって、簡単に適所で実行時コード生成が要求されます。
以下のようなコードがあるとします。実行時 (JIT) コンパイルのプラットフォームでは、意図した通りに動きます (「Message value: Zero」がコンソールに 1 回出力されます)。
using UnityEngine;
using System;
public class AOTProblemExample : MonoBehaviour, IReceiver
{
public enum AnyEnum
{
Zero,
One,
}
void Start()
{
//AOT 問題を警告するには 、manager のタイプは
// Manager ではなく、IManager の必要があります。
IManager manager = new Manager();
manager.SendMessage(this, AnyEnum.Zero);
}
public void OnMessage<T>(T value)
{
Debug.LogFormat("Message value: {0}", value);
}
}
public class Manager : IManager
{
public void SendMessage<T>(IReceiver target, T value) {
target.OnMessage(value);
}
}
public interface IReceiver
{
void OnMessage<T>(T value);
}
public interface IManager
{
void SendMessage<T>(IReceiver target, T value);
}
このコードを IL2CPP スクリプティングバックエンドの事前 (AOT) コンパイルのプラットフォームで実行すると、以下の例外が発生します。
ExecutionEngineException: Attempting to call method 'AOTProblemExample::OnMessage<AOTProblemExample+AnyEnum>' for which no ahead of time (AOT) code was generated.
at Manager.SendMessage[T] (IReceiver target, .T value) [0x00000] in <filename unknown>:0
at AOTProblemExample.Start () [0x00000] in <filename unknown>:0
同様に、Mono スクリプティングバックエンドでは、以下のような類似の例外が発生します。
ExecutionEngineException: Attempting to JIT compile method 'Manager:SendMessage<AOTProblemExample/AnyEnum> (IReceiver,AOTProblemExample/AnyEnum)' while running with --aot-only.
at AOTProblemExample.Start () [0x00000] in <filename unknown>:0
事前 (AOT) コンパイラーは、AnyEnum の T を持つジェネリックメソッド OnMessage のコードを生成する必要があることを察知しません。そのため、このメソッドを飛ばしてそのまま継続します。そのメソッドが呼び出されると、ランタイムコンパイラーは実行できる適当なコードを見つけることができず、このエラーメッセージを出力して失敗します。
このような AOT 問題を避けるために、強制的に適当なコードをコンパイラーから生成させることができます。そのためには、以下のようなコードを AOTProblemExample クラスに加えます。
public void UsedOnlyForAOTCodeGeneration()
{
// IL2CPPはこの行だけ必要です。
OnMessage(AnyEnum.Zero);
// Monoにもこの行が必要です。IManager インターフェース
// ではなくManager 上で直接呼び出します。
new Manager().SendMessage(null, AnyEnum.Zero);
// 例外をもつため、このメソッドが呼び出されたかどうかを確認することができます。
throw new InvalidOperationException("This method is used for AOT code generation only. Do not call it at runtime.");
}
コンパイラーが AnyEnum の T を持つジェネリックメソッド OnMessage を明白に呼び出すと、ランタイムに適切なコードが生成され実行されます。UsedOnlyForAOTCodeGeneration メソッドは呼び出される必要はありません。ただ、コンパイラーが見るように存在しさえすればよいです。
プラットフォームの中には、スレッドの使用をサポートしないものもあります。そのような場合、System.Threading 名前空間を使用するすべてのコードは、実行時に失敗します。また、.NET クラスのライブラリには、暗にスレッドに依存しているものもあります。よく使われる例は System.Timers.Timer クラスで、スレッドのサポートに依存しています。
2018–08–16 編集レビュー 無しに修正されたページ - ページのフィードバックを残す
Samsung TV サポートを削除
.Net 3.5 スクリプティングランタイムは、2018.3 では非推奨です。 NewIn20183
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.