UnityとAndroidの双方向コミュニケーションシリーズ(1)

  Android プラットフォーム上で動作するネイティブ アプリは Android インターフェイスを直接呼び出すため、早い者勝ちの利点を享受できますが、Unity を使用して開発された Android アプリは二級市民のようなものであり、使用するのがはるかに面倒です。 WiFi、Bluetooth などの Android のネイティブ機能、特にいくつかの高度な機能は Unity で完全にはカバーされておらず、Unity で直接開発するだけでは十分ではありません。さらに、クロスプラットフォーム開発のニーズに適応するためには、 Unity のエンジン アーキテクチャ設計は、より複雑かつ柔軟です。Unity エンジンに基づいた開発アプリ アプリケーションは、独立した VM (仮想マシン、仮想マシン) で実行されます ( IL2CPP バックエンドでコンパイルされたアプリケーションは、実行時に仮想マシンのサポートが必要です)。これは、アプリ アプリケーションと Android ネイティブ システム コード間の相互作用に困難をもたらします。実際のアプリケーション開発では、Unity ベースのアプリ アプリケーションとその基盤となる Android プラットフォームとの間でインタラクションが必要になることがよくありますが、このシリーズでは主に Unity エンジンと Android プラットフォームの間のインタラクティブな通信について研究します。

(1) AndroidとUnity間の通信原理

  Unity エンジンの最大の利点と機能は、ワンタイムの制作とマルチエンド展開であり、マルチプラットフォーム ゲームの開発とメンテナンスのコストを大幅に削減します。Unity エンジンが強力なクロスプラットフォーム機能を実現するための基盤は、Mono/ IL2CPP: Mono/IL2CPP は、Unity エンジンのクロスプラットフォーム機能であり、プラットフォームのコアおよび基盤です。

  2001年に電気通信標準化団体ECMAが、特定の言語に依存しないクロスアーキテクチャ実行環境CLI(Common Language Infrastructure)の標準仕様を策定し、この仕様で定義された高級言語を使用して開発する限り、アプリケーションは準拠することになります。つまり、異なるコンピュータ アーキテクチャ上でのクロスプラットフォーム動作を保証できます。これに基づいて、Microsoft は標準に従って .NET Framework Common Language Runtime (CLR) を実装しました。したがって、CLR は CLI の実装です。.NET Framework は CLR に基づいて実行されるフレームワークです。C#、VB.NET をサポートします。 、C++、Python などの言語に対応していますが、.NET Framework と Windows の間には深い関係があるため、.NET Framework 自体はクロスプラットフォームではありません。

  Mono は、Xamarin が主導するもう 1 つの CLI 実装であり、組み込みの C# 言語コンパイラー、CLR ランタイム、およびさまざまな基本クラス ライブラリを使用して、Windows、Linux、FreeBSD、Android、iOS などのさまざまなプラットフォームでアプリケーションを実行できるようにします。 Android または iOS アプリケーションは、Mono を通じて C# 言語を使用して作成できます。CLI 仕様では、高級言語は直接マシン バイトコードにコンパイルされるのではなく、高級言語とマシン バイトコードの間の特定の基礎となる言語である中間言語 (Intermediate Language、IL) にコンパイルされます。ハードウェアに依存しない言語の場合、IL は、実際に実行する必要があるときに Mono VM にロードされます [Unity は、C#、Unity Script、Boo の 3 つのスクリプト開発言語をサポートしており、すべての高水準言語は次のようにコンパイルされます) IL中間言語。] を実行すると、VM はそれを動的にマシンコードにコンパイルして実行します (Just In Time、JIT コンパイル)。その実行プロセスを図 1(a) に示します。
ここに画像の説明を挿入します

図 1 Mono のコンパイルと実行コード、および IL2CPP のコンパイルと実行コードの概略フローチャート
  Mono を通じて、Unity エンジンはアプリケーションをさまざまなシステム プラットフォームにデプロイし、クロスプラットフォーム操作を実現できます。ただし、IL は Mono VM で実行され、Mono VM はシステム プラットフォームと密接に関連しており、クロスプラットフォームに対応できないため、Unity はさまざまなプラットフォーム上で多数の Mono VM を維持する必要があり、JIT コンパイル方式では実行速度も低下します。このため、Unity エンジンは IL2CPP バックエンド コンパイル メソッドを導入し、IL を C++ コードに再コンパイルし、C++ コンパイラーによってネイティブ アセンブリ コード (Ahead Of Time、AOT コンパイル) に直接コンパイルされることで、コードの実行を向上させます。効率性が高く、各プラットフォームの C++ コンパイラを使用してコンパイル時の最適化を行うことができますが、高級動的言語の特性により、メモリ管理とリサイクルは依然として統合されたメンテナンス、つまり IL2CPP VM が必要ですは GC、スレッド、その他のサービス作業を担当する必要がありますが、現時点では IL2CPP VM は IL ロードと動的解析を担当しなくなり、VM を保守する作業負荷が大幅に軽減されます。


  IL2CPP は、最終的には AOT 方式を使用して各プラットフォームのネイティブ マシン コードに直接コンパイルされますが、IL 中間言語のメカニズムを継承しており、上位層の言語にはほとんど影響を与えません ( C++ は静的言語であり、 AOT 方式と JIT 動的言語の一部の機能は利用できなくなります) が、図 1(b) に示すように、メモリ管理やその他の作業のために VM の助けも必要になります。Android ネイティブ アプリケーションは Java 言語で書かれており、Java 言語はまずバイトコード IL 中間言語にコンパイルされ、次に Android 上の dalvik/art 仮想マシンに依存して解釈と実行が行われます。したがって、図 2 に示すように、Unity エンジンと Android ネイティブ コード間の対話型通信は、実際には 2 つの VM 間の通信になります。Unity コードと Android ネイティブ コードは異なる VM で実行されますが、両方とも同じプロセス内にあるため、データを共有できます。

ここに画像の説明を挿入します

図2 UnityとAndroid間の対話型通信の模式図
  図 2 では、Unity エンジンは UnityEngine によって提供される API を通じて Android メソッドを呼び出し、Android は com.unity3d.player パッケージによって提供される API を通じて Unity メソッドを呼び出します。このようにして、Unity エンジンは Android クラスとオブジェクトのメソッドを直接呼び出すことができますが、Android は Unity の指定されたゲームオブジェクトにマウントされたスクリプトのメソッドを呼び出すか、動的プロキシを介して Unity エンジンのメソッドを呼び出すことしかできません。

  実行レベルでは、UnityEngine は AndroidJavaObject、AndroidJavaClass、および AndroidJavaProxy クラスをカプセル化します。これらのクラスを通じて、Android 側の静的クラスまたは動的オブジェクトを取得できるため、対応するメソッドを実行できます。Android は mainActivity を通じて C# コードと通信します。 Unity アプリケーションの [このセクションで説明する Unity と Android 間の対話型通信は、基本的に C# コードと Java コード、JAR パッケージ、AAR パッケージ、および SO パッケージ間の相互呼び出しを指しますが、慣例的には Unity エンジン間の通信として説明されます。 Android オペレーティング システム ソフトウェア。]。

  アクティビティは、Android アプリケーションの最も基本的かつ重要なコンポーネントの 1 つです。その機能は、Web のページや winform のフォームに似ています。したがって、アクティブなアクティビティのみが入力に応答できます。そのため、Android コードは最初に com を渡す必要があります。 unity3d. player.UnityPlayer パッケージの下の currentActivity はアクティブなアクティビティを取得し、それを使用して Unity コードと通信します。

(2) Unity が Java コードを直接呼び出す

  Unity2018 以降のバージョンでは、Android 側でのコンパイル、ビルド、パッケージ化に一律に Gradle を使用し、Android Studio もコンパイル、ビルド、パッケージ化に Gradle を使用します。つまり、これらはすべて同じコンパイルおよびビルド ツール、つまり Java コードとC# コードは Unity で Android 側に正しくコンパイルされ、Unity で Java および C# 言語を直接使用するための基礎を築きます。

  Java データ構造のマッピングを容易にするために、いくつかのカプセル化されたクラスが UnityEngine クラスに組み込まれています。最も重要なクラスは、AndroidJavaClass、AndroidJavaObject、および AndroidJavaProxy です。これらのクラスは、Java 側と C# 側の間の相互呼び出しの基礎です。 。AndroidJavaClass は Unity の java.lang.Class クラスの表現です。主にクラス構造の反映、クラスの静的属性の取得、またはクラスの静的メソッドの呼び出しに使用されます。そのパブリック メソッドを表 1 に示します。

表 1 AndroidJavaClass パブリック メソッドのリスト
パブリックメソッド 呼び出し元のオブジェクト/プロパティ タイプ 一般的なメソッド 説明する
電話 非静的 電話 オブジェクトの非静的メソッドを呼び出す
コールスタティック 静的 コールスタティック クラスの静的メソッドを呼び出す
得る 非静的 得る オブジェクトの非静的プロパティを取得する
GetStatic 静的 GetStatic クラスの静的プロパティを取得する
セット 非静的 セット オブジェクトの非静的プロパティを設定する
SetStatic 静的 SetStatic クラスの静的プロパティを設定する
GetRawClass - GetRawClass JNI で使用するネイティブ Java 型へのポインタを取得します。
GetRawObject - GetRawObject JNI で使用するネイティブ Java オブジェクトへのポインタを取得します。
廃棄 - - IDisposable インターフェイス コールバック

  AndroidJavaObject は Unity の java.lang.Object クラスの式であり、java.lang.Object クラスは Java のすべてのクラスの基本クラスであるため、すべての Java オブジェクトを受け入れることができます。そのパブリック メソッドを表 2 に示します。

表 2 AndroidJavaObject パブリック メソッドのリスト
パブリックメソッド 呼び出し元のオブジェクト/プロパティ タイプ 一般的なメソッド 説明する
電話 非静的 電話 オブジェクトの非静的メソッドを呼び出す
コールスタティック 静的 コールスタティック クラスの静的メソッドを呼び出す
非静的になる 得る オブジェクトの非静的プロパティを取得する
GetStatic 静的 GetStatic クラスの静的プロパティを取得する
セット 非静的 セット オブジェクトの非静的プロパティを設定する
SetStatic 静的 SetStatic クラスの静的プロパティを設定する
GetRawClass - GetRawClass JNI で使用するネイティブ Java 型へのポインタを取得します。
GetRawObject - GetRawObject JNI で使用するネイティブ Java オブジェクトへのポインタを取得します。
廃棄 - - IDisposable インターフェイス コールバック
  表 1 と表 2 からわかるように、これら 2 つのクラスのパブリック メソッドはまったく同じであるため、開発者はこれら 2 つのクラスを使用するときに完全に一貫した外観を得ることができます。使用時は、AndroidJavaClassクラスのforName()メソッドと.class属性を介して、対応するクラスのオブジェクトが生成されますが、Classクラスのメソッドはリフレクションによく使われるため、静的プロパティや静的メソッドの呼び出しに使用するのが一般的です。 AndroidJavaObject は getClass を通じてオブジェクトを表します () メソッドはオブジェクトの型を取得できるため、通常はオブジェクトのインスタンス メソッドまたはプロパティを呼び出すために使用されます。たとえば、静的メソッド StaticMethod() とインスタンス メソッド InstanceMethod() を持つクラス com.davidwang.util がある場合、 new AndroidJavaClass("com.davidwang.util").callstatic("StaticMethod") は同等です。 util.StaticMethod(); の呼び出しと new AndroidJavaObject("com.davidwang.util").call("InstanceMethod") は new Util().InstanceMethod() と同等です。

おすすめ

転載: blog.csdn.net/yolon3000/article/details/135005458