Android Studio与Unity3D实现交互通信开发

概述

Unity开发过程中,需要用到某些java库或者java接口实现比较方便,这时候就需要用到unity3D与AndroidStudio交互开发,由AndroidStudio生成集成的包,导入到unity3D后使用.

但是之前一直没搞清楚,如何实现java和c#的通信和调用,很多旧的方法都是导入jar包,导入mainfest.xml等,导了一大堆东西出来,调用的时候还特麻烦,最近参考其他大佬的方案,深入研究了一下,整理出来一个接口调用简单,只需要导出aar包的方法,大部分方法和接口都已经封装好了,最大程度上去除了Android和unity开发的耦合性.

先贴上源码地址: Android及unity源码

大致执行逻辑:

  1. Android中提供Java方法调用接口;
  2. Unity调用Java接口方法;
  3. Java执行具体逻辑;
  4. Java回调Unity方法,返回计算结果。

Android Studio部分

作用:

  • 实现Java逻辑;
  • 提供供Unity调用的方法接口;
  • 回调Unity方法(主要是将Java运算结果返回到Unity中)

此方法只需生成aar包即可.

  1. 新建Android Studio工程,工程名字随意命名,因为后续用不到它.比如叫做AndroidvsUnity.
    软件版本应该无所谓,我用的3.2.
    Android Studio与Unity3D实现交互通信开发_第1张图片
  2. SDK版本尽量选择unity开发过程中需要的版本,没有要求的话,我这里选的6.0;
    Android Studio与Unity3D实现交互通信开发_第2张图片
  3. 因为是创建arr包,app中不需要管,所以开始不需要像应用开发那样创建Activity,选择no Activity即可,后面的类和Activity在新创建的模块中实现;
    Android Studio与Unity3D实现交互通信开发_第3张图片
  4. 点击finish后,工程就创建完成了;
  5. 接下来,创建一个新的Moudle,这里需要稍微注意一下,我们这里创建的是arr包,不是apk应用,所以这里应该选择"Android Library";
    Android Studio与Unity3D实现交互通信开发_第4张图片
  6. 这里的moudle的名字是导入unity的aar包,所以要认真取个名字;
    Android Studio与Unity3D实现交互通信开发_第5张图片
  7. 接下来,创建几个通信类,可以参照我这里的名字,也可以任意取别的类名.
    Android Studio与Unity3D实现交互通信开发_第6张图片

下面是几个类的源码,具体功能在注释中已经写的很清楚了.

AndroidCallBack: 供unity调用Android方法
IUnityCallBack: 供Android调用unity方法
UnityCallBackSingleton: Android调用unity方法的辅助类.

1. AndroidCallBack.java

/**
 * Android方法,在与Unity通信开发过程中,供Unity调用.
 * 用于unity调用java方法的初始化啊,参数传递啊之类的操作.
 */
public class AndroidCallBack {
    private static final String TAG = "AndroidCallBack";

    /**
     * Unity中调用方法.
     * 应在unity中的onstart()方法中,调用此方法,设置callback.
     * @param callback unity中实现IUnityCallBack接口的类的对象,其中实现了IUnityCallBack接口声明的各个方法,供Android调用.
     */
    public void setAndroidUnityCallback(IUnityCallBack callback){
        try {
            UnityCallBackSingleton.getInstance().setUnityCallback(callback);
        }
        catch (Exception ex)
        {
            Log.v(TAG,ex.toString());
        }
    }

    /**
     * Android方法,供unity调用,获得unity传入多个参数,执行相关动作.
     * @param param 传入string参数.
     * @param array 传入int[]参数
     */
    public void androidFunc(String str, int[] array){

        Log.d(TAG, "androidFunc: get a string from unity: " + str);
        Log.d(TAG, "androidFunc: get a array from unity: " + Arrays.toString(array));


        //Android主动调用unity中的方法.
        IUnityCallBack callBack = UnityCallBackSingleton.getInstance().getUnityCallback();
        if(callBack != null){
            String unityStr = callBack.getUnityStringFunc();                                        //调用unity方法,获取返回值.
            Log.d(TAG, "androidFunc: call the unity function and get the result: " + unityStr);
            callBack.setUnityValueFunc(32, "AndroidString");                          //将Android中的某些值,传入unity.
            Object obj = null;
        }

    }

}

2. IUnityCallBack.java

/**
 * Unity方法调用接口,在此接口中声明Unity中实现的方法,用于在Android开发过程中,调用Unity方法.
 */
public interface IUnityCallBack {
    public String getUnityStringFunc();
    public void setUnityValueFunc(int intValue, String str);
}

3. UnityCallBackSingleton.java

/**
 *单例.用于与unity进行交互,获取unity的Activity和_unityCallback.
 */
public class UnityCallBackSingleton {
    private static final String TAG = "UnityCallBack";

    private static UnityCallBackSingleton mInstance;
    private UnityCallBackSingleton(){
        //do nothing.
    }

    /**
     * 获得单例实例对象.
     * @return
     */
    public static UnityCallBackSingleton getInstance(){
        if(mInstance != null){
            mInstance = new UnityCallBackSingleton();
        }
        return mInstance;
    }

    /**
     * unity项目启动时的上下文
     */
    private Activity _unityActivity;

    /**
     * unity回调方法,实现了用于Android调用的具体方法.
     */
    private IUnityCallBack _unityCallback;


    /**
     * 获取Unity正在启动的Activity.
     * @return
     */
    public Activity getUnityActivity(){
        if(_unityActivity==null) {
            try {
                Class<?> classtype = Class.forName("com.unity3d.player.UnityPlayer");
                Activity activity = (Activity) classtype.getDeclaredField("currentActivity").get(classtype);
                _unityActivity = activity;
            } catch (ClassNotFoundException e) {

            } catch (IllegalAccessException e) {

            } catch (NoSuchFieldException e) {

            }
        }
        return _unityActivity;
    }

    /**
     * 设置callback.
     * @param callback
     */
    public void setUnityCallback(IUnityCallBack callback){
        try {
            _unityCallback = callback;
        }
        catch (Exception ex)
        {
            Log.v(TAG,ex.toString());
        }
    }

    /**
     * 获取callback实例.
     * @return
     */
    public IUnityCallBack getUnityCallback(){
        return _unityCallback;
    }

}

Android Studio端直接build就可以了,可以生成aar包,这就是我们唯一需要导入到unity中的包了.
Android Studio端直接build就可以了,可以生成aar包,这就是我们唯一需要导入到unity中的包了.
Android Studio端直接build就可以了,可以生成aar包,这就是我们唯一需要导入到unity中的包了.

Unity部分

将上述aar包,导入到untiy的Plugins/Android/目录下,没有的话,新建一个.如果Android中用到了其他jar或者aar包,也要一起导进来。
unity部分代码其实也很简单,关键的脚本只有两个,我这里给出了4个脚本文件,其中两个用来与Android端开发交互的,另外两个只是辅助脚本。

脚本设计说明

  1. UnityCallBack.cs: Android调用unity中的方法。用来实现Android中声明的IUnityCallBack接口,实现其接口方法,这样在Android调用IUnityCallBack对象方法的时候,就直接调用了这里实现的方法;
  2. AndroidCallBack.cs: unity调用Android中的方法。
  3. Singleton.cs: C#单例,辅助类。在工程设计过程中,AndroidCallBack作为单例实现,在有需要调用Android方法的地方,直接通过该单例调用即可。
  4. Demo.cs: 功能演示用的脚本。

unity工程配置

以上脚本中,AndroidCallBack.cs随便找个激活的物体挂上就行,相机或者新建一个manager空物体都可以;

Demo.cs挂在需要实现交互操作的物体上,如果测试功能的话,随便挂在哪都可以。

脚本实现

各脚本具体实现如下:

1、UnityCallBack.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// 
/// 用于Android调用unity方法。
/// 实现Android中定义的IUnityCallBack接口方法。
/// unity实现java中的方法,需要继承AndroidJavaProxy。
/// 
public class UnityCallBack: AndroidJavaProxy
{

    public delegate void OnUnityEventAction(string result);
	//Android调用unity方法的事件。
    public static event OnUnityEventAction OnEventCallBack;

    /// 
    /// UnityCallBack构造方法,实现Android中的IUnityCallBack接口。
    /// 
    public UnityCallBack() : base("com.zh.androidtoolslib.IUnityCallBack")
    {
        //Debug.Log("UnityCallBack 构造方法");
    }

    #region 复写Android中IUnityCallBack接口方法,需保证方法名与参数类型、顺序等于Java接口定义完全一致。

    /// 
    /// Android中调用方法,从unity返回一个字符串给Android。
    /// 
    /// 
    public string getUnityStringFunc()
    {
        string str = "a string from Unity.";
        return str;
    }

    /// 
    /// Android中调用方法,通过传入参数,将Android中的某些值,传入unity。
    /// 
    /// 
    public void setUnityValueFunc(string str)
    {
        if (OnEventCallBack != null)
        {
            OnEventCallBack.Invoke(str);
        }
        Debug.Log("get a string frome Android: " + str);
    }
    #endregion

}

2、AndroidCallBack.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Helper.Utilities;

/// 
/// 用于unity调用Android方法。
/// 
public class AndroidCallBack : Singleton<AndroidCallBack> {

    // Android中的java对象
    AndroidJavaObject _ajo;
    void Start()
    {
        //加载java类,生成java类对象。
        _ajo = new AndroidJavaObject("com.zh.androidtoolslib.AndroidCallBack");
        if (_ajo != null)
        {
            //设置Android中的unity回调方法。
            // 因为Android中调用unity方法,是直接调用的IUnityCallBack接口方法,因此要传入IUnityCallBack接口的具体实现对象。
            _ajo.Call("setAndroidUnityCallback", new UnityCallBack());
        }
    }

    /// 
    /// 调用Android方法.
    /// 
    /// string对象
    /// int[] 数组对象
    public void androidFunc(string param, int[] arr)
    {
        if(_ajo != null)
        {
            _ajo.Call("androidFunc", param, arr);
        }
    }

}

3、Singleton.cs

using UnityEngine;

namespace Helper.Utilities
{
    /// 
    /// Singleton behaviour class, used for components that should only have one instance
    /// 
    /// 
    public class Singleton<T> : MonoBehaviour where T : Singleton<T>
    {
        private static T instance;
        public static T Instance
        {
            get
            {
                return instance;
            }
        }

        /// 
        /// Returns whether the instance has been initialized or not.
        /// 
        public static bool IsInitialized
        {
            get
            {
                return instance != null;
            }
        }

        /// 
        /// Base awake method that sets the singleton's unique instance.
        /// 
        protected virtual void Awake()
        {
            if (instance != null)
            {
                Debug.LogErrorFormat("Trying to instantiate a second instance of singleton class {0}", GetType().Name);
            }
            else
            {
                instance = (T)this;
            }
        }

        protected virtual void OnDestroy()
        {
            if (instance == this)
            {
                instance = null;
            }
        }
    }
}

4、Demo.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Demo : MonoBehaviour {
	// Use this for initialization
	void Start () {
        UnityCallBack.OnEventCallBack += this.onEventCallBack;
    }
	
	// Update is called once per frame
	void Update () {
		
	}

    public void onStartBtnClick()
    {
        string str = "A STRING FROM UNITY.";
        int[] arr = { 1, 2, 3, 4, 5 };
        // unity调用Android方法.
        AndroidCallBack.Instance.androidFunc(str, arr);
    }

    /// 
    /// Android调用unity方法的响应事件。
    /// 可在多个脚本中设置不同的响应事件。
    /// 
    /// Android调用unity方法时,传入的参数。 
    private void onEventCallBack(string result)
    {
        Debug.Log(result);
    }
    
    private void OnDestroy()
    {
        UnityCallBack.OnEventCallBack -= this.onEventCallBack;
    }
}

使用说明

Android Studio

Android Studio中,把需要调用unity中的方法,声明在IUnityCallBack接口中,然后直接通过接口类型的对象(该对象是unity在初始化阶段通过调用Android方法传递过来的)调用就可以了。

Android Studio中,把需要供unity调用的方法,写在AndroidCallBack.java中即可。

Unity

unity中,创建一个单例脚本AndroidCallBack.cs,用于实现对Android方法的调用统一管理,任何对Android方法的调用,都通过该单例实现。在该单例脚本中,首先要获取Android定义的AndroidCallBack(该类中包含了供unity调用的方法)对象,然后设置Android中的IUnityCallBack接口对象(该对象为unity中实现了Android中IUnityCallBack接口的类对象)。这样初始化基本上就完成了。

unity中,设计一个类,实现Android中的IUnityCallBack接口,实现其接口方法。这里用了event响应事件,来响应Android调用事件。

结束

主要是利用了java的类反射机制。研究的还不够深入,感觉现在还是有点麻烦,后续如果有应用需求,再继续优化。

你可能感兴趣的:(Android Studio与Unity3D实现交互通信开发)