Unity で Android 連携

はじめに

UnityでiOS連携」では主に Unity と iOS の連携について紹介したので、今回は Unity と Android の連携を紹介します。

Unity と Android 連携

Unity と Android を連携させるには主に `AndroidJavaClass` でインスタンス生成し、`Call` メソッドで Android 側のメソッドを呼び出す流れです。逆の Android から Unity へは iOS 同様 `UnitySendMessage` を使用することで実現できます。Kotlin でも Android Java でも Android ライブラリ(AAR)化すれば、Unity からメソッドを呼び出すことができます。

開発環境

- Mac OS (Mojave)
- Unity 2018.4.9f1
- Android Studio 3.4.1 (Gradle 3.4.1)

手順

1. Android Studio で Androidライブラリ作成用のプロジェクトを作成

2. Android Studio で File -> New -> New Module で Android Library を選択

3. Mac で Unity Hub 使用の場合、Application -> Unity -> Hub -> Editor -> Unity のバージョン -> PlaybackEngines -> AndroidPlayer -> variations -> mono -> Release -> Classes 内の classes.jar を作成した module の libs 配下にコピペしてターゲットを手順2で作成したライブラリにして、「Sync Project with Gradle Files」実行(下図赤枠)

スクリーンショット 2019-11-20 12.08.03

スクリーンショット 2019-11-20 12.07.38

4. 手順3でコピペした classes.jar 配下に bitter.jnibridge, com.unity3d.player, org.fmod が作成されているのを確認(UnityPlayer.UnitySendMessage が呼び出せるようになる)

スクリーンショット 2019-11-21 16.35.56

5. Android側でネイティブの処理を実装

6. module 配下(ライブラリ名 -> build.gradle )の build.gradle 内で dependencies タブ内の implementation fileTree(dir: 'libs', include: ['*.jar'])  を compileOnly fileTree(dir: 'libs', include: ['*.jar']) に変更

7. Gradleタブを開き、module(ライブラリ名)内の Tasks -> build -> assemble をダブルクリックし、ビルド

スクリーンショット 2019-11-20 15.32.23

8. module(ライブラリ名) 内の build -> outputs -> aar にデバック用とリリース用の aar ファイルがあるので、 Unity 側の Assets -> Plugins -> Android 以下に配置

スクリーンショット 2019-11-20 16.03.33

9. Unity側 でネイティブを呼ぶスクリプト作成/修正

10. Unity でビルド

サンプルコード

Unity から Android のアラートダイアログの表示し、アラートダイアログのボタンイベントを Unity 側に返し、ログ表示するサンプルです。

Android(Java)
AndroidAlertDialog.java

package com.sample.androidalertdialog;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;

import com.unity3d.player.UnityPlayer;

public class AndroidAlertDialog {

   public void show(Activity activity,
                    String title,
                    String message,
                    final String gameObjectName,
                    final String positiveMethodName,
                    final String negativeMethodName) {
       new AlertDialog.Builder(activity)
               .setTitle(title)
               .setMessage(message)
               .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                   @Override
                   public void onClick(DialogInterface dialog, int which) {
                       if (!BuildConfig.DEBUG) {
                           UnityPlayer.UnitySendMessage(gameObjectName, positiveMethodName, "OK");
                       }
                   }
               })
               .setNegativeButton("キャンセル", new DialogInterface.OnClickListener() {
                   @Override
                   public void onClick(DialogInterface dialog, int which) {
                       if (!BuildConfig.DEBUG) {
                           UnityPlayer.UnitySendMessage(gameObjectName, negativeMethodName, "キャンセル");
                       }
                   }
               })
               .show();
   }

   public static void showStatic(Activity activity,
                                 String title,
                                 String message,
                                 final String gameObjectName,
                                 final String positiveMethodName,
                                 final String negativeMethodName) {
       new AlertDialog.Builder(activity)
               .setTitle(title)
               .setMessage(message)
               .setPositiveButton("OK", new DialogInterface.OnClickListener() {
                   @Override
                   public void onClick(DialogInterface dialog, int which) {
                       if (!BuildConfig.DEBUG) {
                           UnityPlayer.UnitySendMessage(gameObjectName, positiveMethodName, "OK");
                       }
                   }
               })
               .setNegativeButton("キャンセル", new DialogInterface.OnClickListener() {
                   @Override
                   public void onClick(DialogInterface dialog, int which) {
                       if (!BuildConfig.DEBUG) {
                           UnityPlayer.UnitySendMessage(gameObjectName, negativeMethodName, "キャンセル");
                       }
                   }
               })
               .show();
   }
}

Unity(C#)
*任意のスクリプト(クラス)を作成し、適当な `GameObject` にアタッチして使用することを前提

void PositiveButtonEventListener(string message)
{
   Debug.Log($"<color=aqua>{message}</color>");
}

void NegativeButtonListener(string message)
{
   Debug.Log($"<color=aqua>{message}</color>");
}

#if UNITY_ANDROID
   // UnityのActivity取得
   var unityPackageName = "com.unity3d.player.UnityPlayer";
   var unityActivityName = "currentActivity";
   var activityClass = new AndroidJavaClass(unityPackageName);
   var activity = activityClass.GetStatic<AndroidJavaObject>(unityActivityName);

   // Androidネイティブコード呼び出し
   var alertPackageName = "com.sample.androidalertdialog.AndroidAlertDialog";
   // 通常メソッド
   var alertObject = new AndroidJavaObject(alertPackageName);
   alertObject.Call("show",
       activity,
       "タイトル",
       "メッセージ",
       gameObject.name,
       nameof(PositiveButtonEventListener),
       nameof(NegativeButtonListener));

   // staticメソッド
   /*
   var alertClass = new AndroidJavaClass(alertPackageName);
   alertClass.CallStatic("showStatic",
       activity,
       "タイトル(static)",
       "メッセージ",
       gameObject.name,
       nameof(PositiveButtonEventListener),
       nameof(NegativeButtonListener));
   */        
#endif

サンプルコード解説

基本的には Unity 側で AndroidJavaObject でインスタンスを生成し、メソッドを呼ぶという流れです。もし、static メソッドの場合であれば、 AndroidJavaClass を使用し、 CallStatic でメソッド呼び出しができます。 ネイティブ側で呼び出す UnitySendMessage は iOS の時と同様に第2引数に Unity 側で用意した PositiveButtonEventListener と NegativeButtonListener を定義していて、ボタンイベントで第3引数の文字列を Unity 側のこれらのメソッドで受け取ることを実現しています。注意点も同様に UnitySendMessage で Unity 側に処理されたことを伝えたいが、値(文字列)が不要という場合は UnitySendMessage の第3引数に空文字を設定してください。ただし、Unity 側のコールバックメソッドを引数なしで定義してしまうと処理されたことが通知されないので引数は文字列型を定義することが必須となりますので注意してください。

まとめ

Unity と Android の連携方法を紹介しました。iOS に比べてエラーが特定しやすいですが、手順が多いのが難点ですね。こちらの方法が使えると Unity でできることが増えます。ただし、UnitySendMessage は実行時に 1フレームかかるので、乱用するとフレーム落ちが発生する可能性がありますので注意してください。

この記事が気に入ったらサポートをしてみませんか?