C# スクリプトから Java や Kotlin のプラグインコードを呼び出す
Interact with Java and Kotlin plug-in code from your C# scripts.
読み終わるまでの所要時間 13 分最終更新 1ヶ月前
C# スクリプトから Java コードを呼び出すために、Unity は C++ を通じて Android Java Native Interface と通信する C# API を提供します。JNI を使用して Java コードと相互作用するために使用できる低レベルの API と 高レベルの API の両方を利用できます。
低レベル API
低レベルの AndroidJNI クラスは、JNI 呼び出しをラップして、JNI メソッドに直接マップする静的メソッドを提供します。AndroidJNIHelper API は、主に高レベルの API で使用されるヘルパー機能を提供しますが、特定の状況で役に立つことがあります。
高レベル API
高レベルの AndroidJavaObject、AndroidJavaClass、AndroidJavaProxy の API は、JNI 呼び出しに必要な多くのタスクを自動化します。また、キャッシュを利用して Java への呼び出しを高速化します。 と の組み合わせは、 と の上に構築されていますが、Java クラスの静的メンバーにアクセスするために使える静的メソッドなどの追加機能が含まれています。
AndroidJavaObjectAndroidJavaClassAndroidJNIAndroidJNIHelperAndroidJavaObjectAndroidJavaClass各インタラクションには静的バージョンもあります。
- 静的メソッドを呼び出します (CallStatic)。
- 静的フィールドの値を取得します (GetStatic)。
- 静的フィールドの値を設定します (SetStatic)。
フィールドの値を取得するとき、または値を返すメソッドを呼び出すときは、ジェネリック を使用して戻り値の型を指定します。フィールドの値を設定する場合も、ジェネリックを使用して設定するフィールドの型を指定します。値を返さないメソッドについては、通常の非ジェネリックバージョンの Call があります。
重要: 非プリミティブ型 には、 としてアクセスする必要があります。唯一の例外は文字列で、Java ではプリミティブ型を表さないにもかかわらず、直接アクセスすることができます。
AndroidJavaObject例
このセクションでは、高レベルの と API の使用方法を示すコードサンプルを掲載しています。
AndroidJavaObjectAndroidJavaClassJava 文字列のハッシュコードを取得
using UnityEngine;public class JavaExamples{ public static int GetJavaStringHashCode(string text) { using (AndroidJavaObject jo = new AndroidJavaObject("java.lang.String", text)) { int hash = jo.Call<int>("hashCode"); return hash; } }}
この例で以下を行います。
- を作成し、java.lang.String を表現します。
AndroidJavaObjectコンストラクターは、少なくとも 1 つのパラメーター (インスタンスを構築するクラスの名前) を取ります。クラス名の後のパラメーターは、オブジェクトのコンストラクター呼び出し用です。この場合は、AndroidJavaObjectのGetJavaStringHashCodeパラメーターです。text - hashCode() を呼び出し、文字列のハッシュコードを取得します。この呼び出しでは、の
Callジェネリック型パラメーターを使用します。intはハッシュコードを整数で返すからです。hashCode()
ノート: ネスト状の Java クラスのインスタンス化にはドット付き表記を使用できません。内部クラスをインスタンス化するには、 セパレーターを使用する必要があります。例えば、 クラスが クラスにネストされている場合、 または を使用します。
$LayoutParamsViewGroupandroid.view.ViewGroup$LayoutParamsandroid/view/ViewGroup$LayoutParamsキャッシュディレクトリを取得
以下のコードサンプルは、プラグインを使用せずに、C# で現在のアプリケーションのキャッシュディレクトリを取得する方法を示しています。
using UnityEngine;public class JavaExamples{ public static string GetApplicationCacheDirectory() { using (AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) using (AndroidJavaObject currentActivity = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity")) using (AndroidJavaObject javaFile = currentActivity.Call<AndroidJavaObject>("getCacheDir")) { string cacheDirectory = javaFile.Call<string>("getCanonicalPath"); return cacheDirectory; } }}
この例で以下を行います。
- を作成し、
AndroidJavaClassを表現します。静的メンバーにアクセスするには、com.unity3d.player.UnityPlayerの代わりにAndroidJavaObjectを使用するのが最も効率的です。AndroidJavaClass - を作成し、現在の Activity を表します。これは、
AndroidJavaObjectの静的メンバーです。com.unity3d.player.UnityPlayer - Activity オブジェクトに対して getCacheDir() を呼び出します。これは、キャッシュディレクトリを表す File オブジェクトを返します。
- File オブジェクトに対して getCanonicalPath() を呼び出します。これは、キャッシュディレクトリを文字列として取得できます。
ノート: この例は参考用です。代わりに、アプリケーションのキャッシュとファイルディレクトリにアクセスするには、Application.temporaryCachePath と Application.persistentDataPath API を使用してください。
Java から Unity にデータを渡す
以下のコードサンプルは、 を使用して Java から Unity にデータを渡す方法を示しています。
UnitySendMessageusing UnityEngine;public class JavaExamples : MonoBehaviour{ private void Start() { AndroidJNIHelper.debug = true; using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) { jc.CallStatic("UnitySendMessage", "My GameObject", "JavaMessage", "NewMessage"); } } private void JavaMessage(string message) { Debug.Log("message from java: " + message); }}
この例で以下を行います。
- を作成し、
AndroidJavaClassを表現します。com.unity3d.player.UnityPlayer - のメンバーである静的な
com.unity3d.player.UnityPlayerメソッドを呼び出します。UnitySendMessage
UnitySendMessageJavaMessageベストプラクティス
ここでは、C# スクリプトから Java や Kotlin のプラグインコードを呼び出す際に知っておくとよい効果的な方法を説明します。
JNI 呼び出しの最小化
Java Native Interface (JNI) を、高レベルまたは低レベルの C# API を介して使用すると、リソースを消費し、速度が低下する可能性があります。パフォーマンスを向上させ、またコードを明確にするために、JNI 呼び出しの数を少なくすることが効率的です。
不必要な JNI 呼び出しを避けるため、高レベルの C# API は、呼び出した各 Java メソッドの ID をキャッシュします。これは、同じメソッドへの後続の呼び出しが、最初の呼び出しほどリソースを消費しないことを意味します。この呼び出しは同じフレーム内である必要はなく、同じ AndroidJavaObject/AndroidJavaClass インスタンスからでなくてもかまいません。低レベル API を使用していて、このパフォーマンス上の利点を求める場合は、自分でメソッド ID をキャッシュする必要があります。そうでない場合は、高レベルの API を使用するのがより効率的です。
ノート: Unity はアプリケーションを 閉じる までキャッシュを維持します。これには、アプリケーションがバックグラウンドで動作している間も含まれます。
ガベージコレクション
AndroidJavaObjectAndroidJavaClassusingusing以下のコードサンプルは、 ステートメントを使って、最適な方法でシステム言語を取得する方法を示しています。
usingusing UnityEngine;public class LocaleExample : MonoBehaviour{ void Start() { using (AndroidJavaClass cls = new AndroidJavaClass("java.util.Locale")) using (AndroidJavaObject locale = cls.CallStatic<AndroidJavaObject>("getDefault")) { if (locale != null) { Debug.Log("current lang = " + locale.Call<string>("getDisplayLanguage")); } } }}