Unity开发过程中,需要用到某些java库或者java接口实现比较方便,这时候就需要用到unity3D与AndroidStudio交互开发,由AndroidStudio生成集成的包,导入到unity3D后使用.
但是之前一直没搞清楚,如何实现java和c#的通信和调用,很多旧的方法都是导入jar包,导入mainfest.xml等,导了一大堆东西出来,调用的时候还特麻烦,最近参考其他大佬的方案,深入研究了一下,整理出来一个接口调用简单,只需要导出aar包的方法,大部分方法和接口都已经封装好了,最大程度上去除了Android和unity开发的耦合性.
先贴上源码地址: Android及unity源码
大致执行逻辑:
作用:
此方法只需生成aar包即可.
下面是几个类的源码,具体功能在注释中已经写的很清楚了.
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中的包了.
将上述aar包,导入到untiy的Plugins/Android/目录下,没有的话,新建一个.如果Android中用到了其他jar或者aar包,也要一起导进来。
unity部分代码其实也很简单,关键的脚本只有两个,我这里给出了4个脚本文件,其中两个用来与Android端开发交互的,另外两个只是辅助脚本。
以上脚本中,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的类反射机制。研究的还不够深入,感觉现在还是有点麻烦,后续如果有应用需求,再继续优化。