いんでぃーづ

個人でゲーム開発してる上で吸収したモノたち紹介。UnityからGIMPまでなんでも。デザインとかゲーム論まで語っちゃうよ的なアレ。

MENU

AndroidプラグインからUnityの関数を呼び出す - UnitySendMessage

{スポンサーリンク}
{スポンサーリンク}

以前の記事でAndroidプラグインの関数を呼び出す方法を書きました。

逆にAndroidからUnityのメソッドを呼び出したい場合、もう一手間必要となります。


目次

今回は以前の記事でネイティブプラグインの作り方を理解されてから読んでいただけると幸いです。

また、上記のプロジェクトを引き続き使います。

事前準備:コールバックに必要な jar ファイルをインポート

Android側からUnityのクラスを認識するために jar ファイルをインポートする必要があります。

公式サイトの「UnityPlayerActivity Java コードの拡張」の以下の部分に従って、classes.jar を探します。

これを行うには、まず Unity/Android に付属している classes.jar を探します。このファイルは Unity をインストールしたフォルダー(Windows であれば C:\Program Files\Unity\Editor\Data 、MacOSX であれば /Applications/Unity )のサブフォルダー PlaybackEngines/AndroidPlayer/Variations/mono または il2cpp/Development or Release/Classes/ にあります。

自分はMacを使っているので、今回は /Applications/Unity/PlaybackEngines/AndroidPlayer/Variations/il2cpp/Development/Classes/classes.jar を使ってみます。

これをAndroidStudioプロジェクトの libs フォルダに置きます。

f:id:sugar_affordance:20161209163905p:plain

置いたらAndroidStudioのメニューから

File > Project Structure

と選択し、モジュールのDependencies を表示します。

f:id:sugar_affordance:20161209163934p:plain

左下の「+」ボタンから File Dependency を選択。

f:id:sugar_affordance:20161209164938p:plain

libs に置いた classes.jar を追加します。

このままだと作成したライブラリに classes.jar そのものが含まれてしまうので、dialog-pluin モジュールの build.gradle ファイル の末尾に以下を追加します。

android.libraryVariants.all{ variant->
  variant.outputs.each{output->
    output.packageLibrary.exclude('libs/classes.jar')
  }
}

これでUnityのクラスを認識できるようになりました。

UnitySendMessage 関数でレッツ・コールバック

いよいよUnityの関数を呼び出すのですが、それにあたって必要な情報があります。

  1. シーン内のGameObjectの名前
  2. 関数名

イメージとしてはUnityにある SendMessage 関数をJavaで叩くかんじです。

UnitySendMessage("GameObject名","関数名","引数");

でコールバックできます。

前回作ったプロジェクトのNativeDialogクラスを修正し、ダイアログのどのボタンが押されたかを通知するようにしました。

package jp.co.test.dialog_plugin;

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

import static com.unity3d.player.UnityPlayer.UnitySendMessage;

public class NativeDialog {

    static public void showMessage(Context context, String title, String message) {


        // ボタン入力を受け取るリスナ
        DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialogInterface, int which) {
                switch(which) {
                    case DialogInterface.BUTTON_POSITIVE:
                        // Yesボタン
                        UnitySendMessage("CallbackGameObject", "OnClickOk", "OKが押されたよ!");
                        break;
                    case DialogInterface.BUTTON_NEGATIVE:
                        // Noボタン
                        UnitySendMessage("CallbackGameObject", "OnClickNo", "今回もだめだったよ...");
                        break;
                    default:
                        break;
                }
            }
        };

        // リスナを指定してダイアログ表示
        new AlertDialog.Builder(context)
                .setTitle(title)
                .setMessage(message)
                .setPositiveButton("YES, YES, YES!", listener)
                .setNegativeButton("...No?", listener)
                .show();
    }
}

ビルドしてUnityのプロジェクトにインポートしましょう。

Unity側で受け取る

UnityでシーンにCallbackGameObjectという名前でオブジェクトを配置し、以下のスクリプトをアタッチします。
ひたすらダイアログをコールバックしまくるというウイルスちっくな逸品です。

using UnityEngine;
using System.Collections;

public class AndroidPlugintest : MonoBehaviour {

    void Start () {
        ShowDialog ("もうやってられまへーん");
    }

    void ShowDialog(string message) {
        #if UNITY_ANDROID
        // Javaのオブジェクトを作成
        AndroidJavaClass nativeDialog = new AndroidJavaClass ("jp.co.test.dialog_plugin.NativeDialog");

        // Context(Activity)オブジェクトを取得する
        AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); 
        AndroidJavaObject context  = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");

        // AndroidのUIスレッドで動かす
        context.Call ("runOnUiThread"new AndroidJavaRunnable(() => {

                // ダイアログ表示のstaticメソッドを呼び出す
                nativeDialog.CallStatic (
                        "showMessage",
                        context,
                        "おっさんの主張",
                        message
                    );
            }));
        #endif
    }

    // OKボタンが押された
    void OnClickOk(string text) {
        ShowDialog (text);
    }

    // Noボタンが押された
    void OnClickNo(string text) {
        ShowDialog (text);
    }
}

ちょっと工夫すればメッセージを受け取るGameObjectもUnityから指定できますね。試してみてください。

Unityでビルドエラーが出る場合

Unityでビルドしたときに以下のエラーが出る場合があります。

IOException: Failed to Move File / Directory from 'Temp/StagingArea/android-libraries/dialog-plugin-debug/classes.jar' to 'Temp/StagingArea/android-libraries/dialog-plugin-debug/libs/classes.jar'.

この場合、build.gradleのclasses.jar除外設定をしてあるか確認してください。

よくわからない場合、もう一度最初からこの記事をよんだほうがいいよ。

  • 参考

https://docs.unity3d.com/ja/current/Manual/PluginsForAndroid.html http://qiita.com/abpla/items/a8e4c70953859cdc7c54

Amazon.co.jpアソシエイト