游戏引擎学习之Unity3d&Android通信
Angulu Lv1

游戏引擎学习之Unity3d&Android通信

缘由

Unity3d引擎是跨平台的,但是有时候需要Android平台的Sdk的时候,需要如何进行交互呢?Unity3d提供了一套相关套件,供我们指定平台Sdk和Unity3d(C#)进行通信。

学习工具

Unity3d引擎,Android Studio

实施

我们来测试Unity3d引擎提供的Android通信方案,分为两个步骤测试,新建两个工程,分别是Android工程和Unity3d工程(文后带有下载地址),然后测试各个调用方式

  • 工程构建

1.Android工程构建
构建Android工程和Unity3d(C#)通信,这里使用的是Android Studio构建,步骤如下
1)平常新建Android工程一样,在Android Studio上新建一个简单的工程
2)寻找Unity3d引擎提供的Android编译包,比如,我使用的Unity3d是5.6.2f1版本的,我在安装路径下找到这个jar(我的是在win下的版本)

你的安装目录\Unity\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes
3)将这个jar包复制一份,放到android工程的libs目录下,并在工程根的build.gradle文件中添加一句话

1
2
3
4
5
dependencies {
...
provided files('libs/unity3d.jar')
...
}

此时的jar我已经重命名为unity3d.jar
4)在Android工程的AndroidMainifest.xml文件中meta-data声明Unity3d的绘制Activity,我这里申明的是主Activity,如下

1
2
3
4
5
6
7
8
9
10
...
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="unityplayer.UnityActivity" android:value="true" />
</activity>
...

5)切换到4)步骤中对应的Activity的java文件中,让此Activity集成Unity3d提供的一个父类UnityPlayerActivity,如下:

1
2
3
4
5
6
7
8
public class MainActivity extends UnityPlayerActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}

}

至此,Android工程的准备工作就已经完成了

2.Unity3d工程构建

1)新建Scene和Script文件夹,存放场景和脚本
2)新建Plugins文件夹和在Plugins下再新建Android文件夹(划重点,名字不可变)

至此Unity3d工程已经构建完成

3.Android工程和Unity3d工程的联系建立
1)在Android的主Activity工程里面编写被Unity3d(C#)脚本调用的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
public class MainActivity extends UnityPlayerActivity {

private Context mContext;
private static final String ANDROID_STR = "Android Platform";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = this;
}

public void showToast(){
Toast.makeText(mContext,ANDROID_STR,Toast.LENGTH_LONG).show();
}

public void showToast(String unityStr){
Toast.makeText(mContext, TextUtils.isEmpty(unityStr) ? "null":unityStr,Toast.LENGTH_LONG).show();
}

public String getAndroidStr(){
return ANDROID_STR;
}

}
...

2)将Android工程的代码打成jar包
3)把Android工程打成的jar包,res目录,AndroidManifest.xml放在Unity3d插件目录下
4)现在就可以在Unity3d工程中愉快的调用Android插件提供的方法啦

  • Unity3d ==> Android

初始化相关类,获得调用对象。

1
2
3
4
5
6
7
8
AndroidJavaClass androidjavaClass;
AndroidJavaObject androidjavaObj;

// Use this for initialization
void Start () {
androidjavaClass = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
androidjavaObj = androidjavaClass.GetStatic<AndroidJavaObject> ("currentActivity");
}

1.无参调用

1
2
3
4
5
public void callToast(){
if(null != androidjavaObj){
androidjavaObj.Call ("showToast");
}
}

2.有参调用

1
2
3
4
5
public void callToast2(){
if(null != androidjavaObj){
androidjavaObj.Call ("showToast","unity3d Str");
}
}

3.有返回值

1
2
3
4
5
6
public void callAndroidStr(){
if(null != androidjavaObj){
string rlt = androidjavaObj.Call<string> ("getAndroidStr");
gameObject.GetComponentInChildren<Text>().text = rlt;
}
}
  • Android ==> Unity3d
    Android端调用Unity3d提供的jar包,里面有一个方法
    UnityPlayer.UnitySendMessage(String,String,String)
    三个参数的含义分别是:
  • 1、挂载脚本的对象(此脚本定义了需要调用的方法)*
  • 2、挂载脚本里需要调用的方法名字*
  • 3、需要传递给调用方法的参数字符串*

1.无参调用

1
2
3
public void ChangeObj1(){
gameObject.GetComponentInChildren<Text>().text = "android调用 无参方法";
}

2.有参调用

1
2
3
public void ChangeObj2(string str){
gameObject.GetComponentInChildren<Text>().text = "android调用 有参方法 参数:" + ((str == null ) ? "get null ?":str);
}

注意:为什么要把方法名写的不一样,测试结果显示,若方法名一样,Android端调用Unity端时,只能调用到无参的那个方法。
3.有返回值

UnitySendMessage方法不提供返回值

注意点

1.Android插件的AndroidMainifest.xml的包名最好和Unity3d设置的包名一致
2.unity3d工程的Android apk导出设置需要和插件的AndroidMainifest.xml目标sdk版本一致,不然会导致报错,最好配置都一致。

1
Warning: [Temp\StagingArea\AndroidManifest-main.xml:12, E:\workspace_u3d\Unity3dDemo\Temp\StagingArea\android-libraries\UnityTest-release\AndroidManifest.xml:3] Main manifest has <uses-sdk android:targetSdkVersion='24'> but library uses targetSdkVersion='26'

3.若Android调用Unity3d(C#)方法中有重载方法,只会调用无参的方法

源码地址

Android Demo 源码地址

Unity3d Demo 源码地址