这是一个系列教程,主要内容是如何开发 Unity 插件,在理解这个教程之前需要读者有一定的 Unity、iOS、Android 开发知识
背景
随着手游快速的发展,有着更好的视觉体验的3D游戏更加被玩家所喜爱,Unity3D作为市面上最主流的开发引擎unity常用脚本,使用U3D开发的有些越来越多。开发过程中,不免遇到需要调用Android/iOS原生(Native)方法的情况,本系列教材针对性介绍U3D调用Android/iOS Native代码方式方法。
调用方式简介
U3D调用Native代码的原理,简单来说就是通过中间跨语言调用机制,来实现Native代码调用
Android调用原理
代码调用AndroidNative代码,是基于JNI的机制实现的,好在Unity实现了一套帮助类,可以帮助开发者更简便的调用Android代码,主要的帮助类:
1、AndroidJNI
Unity的JNI底层接口,主要用于实现跟Android虚拟Dalvik之间的方法调用,主要包括:
C#与Java基础类型数据转换
Java类基本操作,包括构造、赋值等
Java方法调用
该类属于较底层的类,在特殊场合下用的到
2、AndroidJNIHelper
JNI的帮助类,封装了几个常见的方法,如数组转换、构造Java参数列表、获取Java方法ID、签名等贴图笔刷,比较少用到
3、AndroidJavaObject
对应Java的基类Object,通过这个类,可以在Unity中直接通过类名构造Android中的Java类
一般我们使用该类进行Android代码调用,主要的方法:
构造方法,可以通过类名直接构造,如:
AndroidJavaObject jo = new AndroidJavaObject("java.lang.String", "some string");
获取和设定成员变量,包括成员变量和静态变量两种:
int m = jo.Get ("member");
jo.Set ("member", 1);
int m = jo.GetStatic ("member");
jo.SetStatic ("member", 1);
方法调用,包含成员方法和静态方法两种,返回值类型在“”中制定,如果返回值为空,无需“”
string substring = jo.Call ("substring", 1, 3);
int i = jo.CallStatic ("valueOf", 1);
注意:返回值类型只能是基础数据类型,如int、string及数组,Android的类可以用AndroidJavaObject来接;复杂类型,如Dictionary等是没有办法直接从Java类直接转成C#类的
4、AndroidJavaClass
这个类很好理解,继承于AndroidJavaObject,与其之间的关系等价于Java中Object与Class的关系,一个是类的实例,一个是类的类型
5、AndroidJavaException
官方文档中查不到,其实很简单,继承于C#的Exception,用于捕获处理Android代码时抛出的异常,可以通过try/catch来捕获Android层的异常
6、AndroidJavaProxy
这个类主要用于在C#环境实例化Java的Interface接口,需要特别注意其语法。
7、AndroidJavaRunnable
这个类与Java中的Runtime对应,用来定义一个可执行类
iOS调用原理
C#调用iOS的代码,实际上是C#提供了一种调用C(非C++)代码的机制,而在iOS环境中,C代码是可以与苹果的Objective-C代码进行混合编译的,这样,就实现了C#调用iOS代码的功能
1、语法说明
非常简单,在Unity的C#的代码中做声明,在C语言中实现具体类容。
Unity中的声明可以是如下形式:
[DllImport ("__Internal")]
private static extern string SomeFunction();
在C语言环境中的实现可以是如下形式:
extern 'C' {
char* SomeFunction() {
char* retString = (char*)malloc(4);
memset(retString, 0, 4);
strncpy(retString, "abc", 4);
return retString;
}
}
如此,就可以实现函数间的对应关系
2、传参说明
由于是C语言,支持的参数及其数据类型是非常有限的,诸如int、float、double、char等这类两种语言中都存在的基础数据类型,是可以实现直接映射的,但是C#中的string对应到C中像素游戏素材,就是char*了
工程结构
Unity在4.X版本以前,对Native的代码调用支持比较有限,只能说是够用;但是到了5.X的版本,Unity对着一块儿增加了很多支持,特别是iOS,比起4.X已经有很大的改善
1、Unity插件支持
Unity中,对于这一类的调用归属到插件(Plugins)的范畴,所以,Android/iOS的相关代码或Library都放在Assets/Plugins目录下。
2、Android工程结构
说到在Unity的插件的工程结构,需要先了解Android本身的工程结构,Unity中采用的还是老式的ADT的目录结构,一般结构如下:
ProjectDir
--assets/*
--libs/*
--res/*
--src/*
project.properties
AndroidManifest.xml
其中,assets是Android下的资源文件;libs下面放jar包或者动态库.so;res下面放资源文件;src目录下放源码
Android的插件一般放在Assets/Plugins/Android目录下。该目录可以理解为Unity的主工程目录,可以按照标准ADT目录结构自行放置文件
如果遇到比较复杂的Android插件,需要依赖一个完整的工程,则可以将整个工程按上面结构整体放在Android目录下,这样,Unity就会将该目录识别为一个工程依赖
3、iOS工程结构
同Android一样,iOS也是Native代码作为插件处理,不过只支持C语言的文件,Objectiv-C特性的文件均不支持unity常用脚本,如framework、bundle文件
所以,iOS一般来讲会用插件来处理,主要有两种:
Xcode Editor For Unity,
XUPorter
基于XCodeEditor开发,
阅读推荐:
腾讯游戏开发者平台