一、应用场景
如果在unity中需要调用android原生的方法,或者anrdroid项目中需要调用unity中的方法实现就需要用到unity和androd之间的相互通信了。
二、在Unity中调用Android的方法
1、在Android项目中新建一个module
2、类型选择「Android Library」
Application/Library name认真填写,之后为arr导出的名称,这里我们叫「MyUnityLib」。
Module name没有强迫症就不用管它
Package name认真填写,之后unity里会用到,不过它和unity导出的包名没有什么关系这里我们叫「com.jing.unity」好了
Minimum SDK能选多低选多低,反正不超过unity发布的版本就行
3、然后我们在com.jing.unity包下创建一个类,作为Unity和Android通信的核心类,名字尽量炫酷一点,这里我们叫「Unity2Android」
4、编写Android端代码
然后我们直接粘贴该类的代码,讲解直接看注释。这里我们通过Java的反射原理来获取本来导入class.jar类才能引用到的com.unity3d.player.UnityPlayer包下的currentActivity上下文。同理给unity发消息也是反射原理。「getActivity」和「callUnity」这两个方法,有一定的开发经验应该很容易理解。
这里我们实现一个简单的接口「showToast」。
package com.jing.unity;
import android.app.Activity;
import android.widget.Toast;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Created by Jing on 2018-1-18.
*/
public class Unity2Android {
/**
* unity项目启动时的的上下文
*/
private Activity _unityActivity;
/**
* 获取unity项目的上下文
* @return
*/
Activity getActivity(){
if(null == _unityActivity) {
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;
}
/**
* 调用Unity的方法
* @param gameObjectName 调用的GameObject的名称
* @param functionName 方法名
* @param args 参数
* @return 调用是否成功
*/
boolean callUnity(String gameObjectName, String functionName, String args){
try {
Class<?> classtype = Class.forName("com.unity3d.player.UnityPlayer");
Method method =classtype.getMethod("UnitySendMessage", String.class,String.class,String.class);
method.invoke(classtype,gameObjectName,functionName,args);
return true;
} catch (ClassNotFoundException e) {
} catch (NoSuchMethodException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
return false;
}
/**
* Toast显示unity发送过来的内容
* @param content 消息的内容
* @return 调用是否成功
*/
public boolean showToast(String content){
Toast.makeText(getActivity(),content,Toast.LENGTH_SHORT).show();
//这里是主动调用Unity中的方法,该方法之后unity部分会讲到
callUnity("Main Camera","FromAndroid", "hello unity i'm android");
return true;
}
}
5、导出arr准备给unity使用
代码写好了我们选中module然后选择「Build」「Rebuild Project」
接着将这个arr文件找到,就是我们要导入到unity的文件了。
6、Unity部分Script的代码内容如下
using UnityEngine;
using UnityEngine.UI;
public class Main : MonoBehaviour {
/// <summary>
/// 场景上的文本框用来显示android发送过来的内容
/// </summary>
public Text text;
/// <summary>
/// android原生代码对象
/// </summary>
AndroidJavaObject _ajc;
void Start () {
//通过该API来实例化导入的arr中对应的类
_ajc = new AndroidJavaObject("com.jing.unity.Unity2Android");
}
void Update () {
}
/// <summary>
/// 场景上按点击时触发该方法
/// </summary>
public void OnBtnClick()
{
//通过API来调用原生代码的方法
bool success = _ajc.Call<bool>("showToast","this is unity");
if(true == success)
{
//请求成功
}
}
/// <summary>
/// 原生层通过该方法传回信息
/// </summary>
/// <param name="content"></param>
public void FromAndroid(string content)
{
text.text = content;
}
}
三、在Android中调用unity中的代码
以上我们实现了unity上调用android的方法,那么android上如何调用unity的方法呢,我们先回到unity的AndroidControl脚本。添加方法OnTimeResult,注意在这里需要导入UnityEngine.UI包usingUnityEngine.UI;
public void OnTimeResult (string result)
{
Text text = GameObject.Find ("TimeShow").GetComponent<Text> ();
text.text = result;
}
上面代码的意思是获取名称为TimeShow的对象,然后将该对象上的Text脚本的文本改为得到的result。所以我们需要将之前的Text对象名称改为TimeShow
回到android的MainActivity,修改方法showToast,让Toast时间的时候同时调用OnTimeResult方法修改text的文本。
public void showToast(final String text) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
public void run() {
if (mToast == null) {
mToast = Toast.makeText(MainActivity.this, text, Toast.LENGTH_SHORT);
} else {
mToast.setText(text);
}
mToast.show();
UnityPlayer.UnitySendMessage("Canvas","OnTimeResult",text);
}
});
}
UnityPlayer.UnitySendMessage(“Canvas”,“OnTimeResult”,text);方法的意思是调用名称为Canvas对象上的OnTimeResult方法,传入的参数为text。