前言
在网络上,有许多关于 Unity 和 Android 互相调用的文章,里面的内容大同小异,都给出了相互调用最基本的方法。在这些文章中,有许多文章是很久之前的,里面的代码放到现在已经无法正常运行了,并且基本都说的比较简单。
本篇文章介绍的是以 Android 项目为主,Unity 项目为辅,以实战场景为基准来实现 Unity 和 Android 的桥接。在这其中,需要考虑桥接的功能型、稳定性、可拓展性、以及结合 Android 原生开发的一些特性。
那么究竟是如何实现的呢,请看下方详解!
一、原理概述
Unity 和 Android 桥接的原理和网络上大多数文章是一致的。
Unity 调用 Android 使用的是C#脚本所提供的 AndroidJava 系列工具类。
C#代码如下:
var javaClass = new AndroidJavaClass("[Java class package name]");
javaClass.CallStatic<string>("methodName", "params1");
使用AndroidJavaClass调用是即方便又强大的,支持回调和返回值。且性能优秀。
Android 调用 Unity 使用的是 Unity 提供的 Jar包里的方法。代码如下:
UnityPlayer.UnitySendMessage(
"Unity Object Name",
"MethodName",
"message"
)
Unity Object Name 为 Unity 中场景对象的名称。
MethodName 为该对象绑定的脚本中的方法。 message 为发送的内容。
可以看到,Android 调用 Unity 的方式没有返回值,且只能是一个字符串类型的参数。所以如果想要达到两端统一调用,就需要一定的封装。那么具体是怎么封装的呢?请继续往下看!
二、架构分析
首先,我们要对 Unity 与 Android 的桥接部分(以下简称:桥接层)进行架构的设计。
注:本篇文章主要讨论以 Android 项目为主的情况,即为,Android 需要为Unity 提供大量功能接口。Unity 为 Android 部分提供少量接口。所以,这里的架构分析主要以 Android 原生部分的桥接层设计来进行后续的讲解。
架构的设计除了桥接层本身提供的业务功能,还需要考虑以下几个点:
- 方法调用设计
- 回调机制的设计
- 可拓展性
- 接入便捷性
- 可移植性
这里先解释一下,为什么需要单独列出来回调机制的设计。在上文原理概述中,可以看到,Android 调用 Unity 的场景不支持回调、返回值和非字符串的传参。所以这里我们如果不进行回调机制的设计,那么将无法满足双方回调的场景。 下面,我们来逐一分析每一个点需要如何满足。
2.1 方法调用
由于 Android 和 Unity 底层提供的相互调用接口不一致,所以如果想要达到相同的调用效果。就需要自行封装一套调用协议。这里,我们使用大家所熟知的 JSON 来作为方法调用协议的载体。
在调用的时候,将方法和其参数、回调信息,封装到一个对象中,序列化为JSON后传给对方。 方法调用协议举例:
{
"name": "methodName",
"callback": false,
"args": [
"{\"name\":\"argName1\",\"value\":\"value1\"}",
"{\"name\":\"argName2\",\"value\":\"value2\"}"
],
"callbackId": "callbackID"
}
上方的 JSON 就是方法对象序列化后的内容。方法对象的定义:
data class Command(
/**
* 指令名称
* 回调情况下name为回调ID
*/
var name: String,
/**
* 是否是回调指令
*/
var callback: Boolean,
/**
* 参数List
*/
var args: List<String>,
/**
* 回调I