在网络上,关于Unity与Android如何进行交互,雨松MOMO大神已经有两篇文章简单介绍了如何操做(1)Unity3D研究院之打开Activity与调用JAVA代码传递参数(2)Unity3D研究院之与Android相互传递消息。这两篇文章简单介绍如何操做,可是具体的内部细节并无涉及到。下面介绍两种Unity与Android交互的方式(或者说就是接入Android SDK),分别是(1)Unity导出Android工程,而后你将SDK工程做为Library来接入(2)Plugins方式,这种方式就是在Assets目录下新建Plugins/Android目录,把你须要的资源、jar包等按规定放进去。android
经过在Build Settings中选择Google Android Project选项,点击Export,能够获得一个Unity生成的Android项目。
将项目导入到Eclipse中,能够看见以下的项目结构:
让咱们先无论src的源代码,首先关注libs。网络
libs有三部分:前二者(armeabi-v7a, x86)表示手机的两种硬件设备,包含了各自所需的so文件,咱们能够在Unity的Player Settings->Other Settings->Device Filter中来进行选择。而unity_classes.jar就是UnityPlayerActivity类所在的jar包,其实就是Unity目录下的Editor\Data\PlaybackEngines\AndroidPlayer\Variations\il2cpp\Development\Classes\classes.jar。(注意,这个路径是Unity5.3的路径,不一样版本的Unity中,该路径是不一样的)
下面咱们来查看classes.jar(即unity_classes.jar)的内容eclipse
在网上下载一个Java反编译工具,好比JD-GUI,打开classes.jar,咱们能够看见以下结构:
其中jnibridge应该是用来实现Java与其余语言的通讯,而fmod是用来控制音频的,剩下的com.unity3d.player才是咱们须要重点关注的。一般咱们本身新建立的Activity,都是要继承UnityPlayerActivity类,所以咱们首先查看该类,其部份内容以下:
该类的内容十分简单,其中最为重要的是UnityPlayer:
回忆一下,咱们在Android里定义本身的Activity:
public class UnityTestActivity extends UnityPlayerActivity
在Unity里调用Android的方法的步骤:函数
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"); jo.Call("StartActivity0","第一个Activity");
由于咱们继承了UnityPlayerActivity,那么当咱们的UnityTestActivity调用onCreate方法时,就同时把本身这个实例传递到了UnityPlayer中的currentActivity。所以在Unity中咱们就能够利用currentActivity来调用咱们自定义的UnityTestActivity中的方法。
这时回头查看src的源代码,能够发现其内容和classes.jar中差很少。工具
一个默认的清单文件中有如下重要内容:
这里,package是在Player Settings->Other Settings->Bundle Identifier设置。默认UnityPlayerActivity为主Activity。布局
除了经过导出Android工程来查看自动生成的内容,也能够经过Unity安装目录下的Editor\Data\PlaybackEngines\AndroidPlayer
来查看,其目录内容以下:
咱们重点看Apk、Source、Variations,这三者里面就包含默认的AndroidManifest.xml,res目录和assets目录等。测试
咱们能够经过在Plugins/Android中添加东西来影响Unity生成的Android项目。ui
咱们能够直接在Android目录下添加一个AndroidManifest.xml文件,这个文件会影响最终的Android项目中的清单文件。注意,这里的程度只是影响,而不是彻底替换,好比package会最终替换为Bundle Identifier的设置,若是没有如下几行3d
<uses-feature android:name="android.hardware.touchscreen" android:required="false" /> <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false" /> <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false" />
若是是默认设置他也会默认加上去,等等。
PS: AndroidManifest.xml要放到Android目录下才会对主清单文件起做用,若是你放到其余目录,好比test,则不会对最终的Android项目有做用。调试
你能够在Android目录下增长一个res目录。无论这个目录是空的仍是有东西,导出来的Android项目都会多一个叫unity-android-resources的Library工程,而咱们的主Android工程则引用了该Library,如图:
观察这个Library就知道,这个工程主要就是存放资源的,好比咱们这里把东西放到res目录中,则这些多出来的东西就会放到Library工程中。注意,res目录的东西不能随便乱放,要按照合格的目录结构来,即通常以下:
若是你是随便把资源放到res目录下,或其余错误名字的子目录,好比res/test等目录下,都会报出如下的错误:
assets目录和res目录相似,都是存放资源的,只是res目录里面的资源会在R文件中生成ID,而assets目录不会生成ID,须要本身手动根据路径来访问资源。
在查看网上的相关文章时,发现大多数文章都说要把jar包放到Plugins/Android目录的libs或bin目录。不知道是否是Unity5作出了修改,我发现jar包无论放到哪,只要在Assets目录下,都能起做用,成为最终Android工程的libs中的内容。
你能够在Plugins/Android目录下放置一个Android Library工程,只要设置得当,这个工程就会被Unity识别并在最终生成的Android工程中引用。这个也是我接入Android SDK时主要使用的方式,十分方便而且易于管理(毕竟这让你知道哪些资源、jar包是归哪一个SDK的。而若是全部资源都放在res目录,jar包都放在libs目录,这样就不知道某个SDK本来的东西在哪了)
下面介绍我接入SDK时的流程,这只是我我的感受比较方便的流程,若是你们有更好的流程,但愿能在评论区告知。我通常会同时使用上述两种方式,由于第一种方式的缺点是很差进行项目管理(毕竟有两个分开的项目),而且要打包一个apk也比较麻烦;而第二种方式的缺点就是不直观,调试不方便。
根据文档,将须要的功能以Unity易于调用的方式写成接口,好比我通常定义函数签名为void FuncName(String params, String callbackTarget, String callbackMethod)
这里,params就是SDK接口须要的参数(或者是参数列表,以";"等分隔符链接具体的参数,好比: "Apple;12"),callbackTarget就是Unity里调用回调方法的GameObject的名字,而callbackMethod就是回调方法的名字。
而后建立简易的界面(好比几个按钮)来调用这些写好的接口,肯定接口的功能无误
去掉Demo工程中测试用的Activity、布局文件,在清单文件中去掉主Activity的设置,最后把项目设置为Library。
导入完成后,若是你的Library工程用到classes.jar,你须要先删掉该classes.jar,而后再添加Unity的Android工程的unity_classes.jar引用。
经过(3),咱们能够获得一个设置正确的Library工程,这时候咱们能够直接把该工程拖到Unity工程的Plugins/Android目录下
(1)Unity在直接导出Apk时,会在Temp目录(与Assets目录同级)下的StagingArea目录生成一些临时的Android代码
(2)在Eclipse中,若是adb一直提示断开链接,能够用360手机助手连上手机,这时adb就能正常工做了
Unity3D研究院之打开Activity与调用JAVA代码传递参数
Unity3D研究院之与Android相互传递消息
Creating a native Android plugin for Unity3d
Unity Android plugin tutorial