转自:http://www.wxdgame.com/blog/2015/11/08/study2/
因为unity需要接入java的sdk,所以今天主要学习了一下相关的通信方法。需要先做如下准备工作:
1、下载android SDK安装包,http://pan.baidu.com/s/1dDGM8oD,里面会包含sdk和eclipse两个文件夹;
2、unity工程从Build Settings界面选择android平台,选中Google Android Projects,导出安卓工程;
3、打开eclipse导入安卓工程,测试编译通过。
有两种方法可以让unity跟java进行通信:
第一种写法,在eclipse中自定义个包名,在里面创建一个类,例如我自定义了com.sdk.SDKAPI:
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 27 28 29 30 31 32 33 34 35 36 37 | package com . sdk ; import org . json . JSONException ; import org . json . JSONObject ; import android . os . Bundle ; import android . util . Log ; import com . unity3d . player . * ; public class SDKAPI { private String test ( int a , String b ) { Log . i ( “unity” , “test: “ + a + ” “ + b ) ; JSONObject obj = new JSONObject ( ) ; try { obj . put ( “first” , 43 ) ; obj . put ( “second” , “testCall” ) ; } catch ( JSONException e ) { e . printStackTrace ( ) ; } com . unity3d . player . UnityPlayer . UnitySendMessage ( “ARCamera” , “UnityTest” , obj . toString ( ) ) ; return “wxd” ; } private static int test1 ( int a , String b ) { Log . i ( “unity” , “test1: “ + a + ” “ + b ) ; JSONObject obj = new JSONObject ( ) ; try { obj . put ( “first” , 55 ) ; obj . put ( “second” , “test1Call” ) ; } catch ( JSONException e ) { e . printStackTrace ( ) ; } com . unity3d . player . UnityPlayer . UnitySendMessage ( “ARCamera” , “UnityTest” , obj . toString ( ) ) ; return 6543 ; } } |
打开AndroidManifest.xml文件,在application节点下有若干个activity节点,找到android:name=”com.xxxxx.UnityPlayerNativeActivity”属性,后面字符串显示的是目前java工程中当前正在使用的activity类文件,把他改成我们刚才自定义的com.sdk.SDKAPI,然后在unity中代码如下:
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 27 28 29 30 31 32 33 34 35 | using UnityEngine ; using System . Collections ; public class GameWorld : MonoBehaviour { private AndroidJavaClass _class ; void Start ( ) { _class = new AndroidJavaClass ( “com.sdk.SDKAPI” ) ; } void UnityTest ( string b ) { Debug . Log ( “UnityTest — “ + b ) ; } void OnGUI ( ) { if ( GUI . Button ( new Rect ( 0 , 0 , 200 , 100 ) , “test …” ) ) { if ( _class != null ) { string a = _class . Call < string > ( “test” , 119 , “wxdgame” ) ; Debug . Log ( “::1:::” + a ) ; } } if ( GUI . Button ( new Rect ( 0 , 100 , 200 , 100 ) , “test1 …” ) ) { if ( _class != null ) { int b = _class . CallStatic < int > ( “test1” , 911 , “testgame” ) ; Debug . Log ( “::2:::” + b ) ; } } } } |
编译运行通过,点击我们放置的按钮,查看log输出,于是我们得到了两个结论:1、java类中的私有方法也可以被unity调用;2、只能调用静态方法。如果我想调用java非静态方法怎么办呢?于是就有了第二种写法,我们修改下unity的代码:
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 27 28 29 30 31 32 33 34 35 36 37 | using UnityEngine ; using System . Collections ; public class GameWorld : MonoBehaviour { private AndroidJavaClass _class ; private AndroidJavaObject _obj ; void Start ( ) { _class = new AndroidJavaClass ( “com.unity3d.player.UnityPlayer” ) ; _obj = _class . GetStatic < AndroidJavaObject > ( “currentActivity” ) ; } void UnityTest ( string b ) { Debug . Log ( “UnityTest — “ + b ) ; } void OnGUI ( ) { if ( GUI . Button ( new Rect ( 0 , 0 , 200 , 100 ) , “test …” ) ) { if ( _obj != null ) { string a = _obj . Call < string > ( “test” , 119 , “wxdgame” ) ; Debug . Log ( “::1:::” + a ) ; } } if ( GUI . Button ( new Rect ( 0 , 100 , 200 , 100 ) , “test1 …” ) ) { if ( _obj != null ) { int b = _obj . CallStatic < int > ( “test1” , 911 , “testgame” ) ; Debug . Log ( “::2:::” + b ) ; } } } } |
同时java里的代码也要进行调整:
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 27 28 29 30 31 32 33 34 35 36 37 38 | package com . sdk ; import org . json . JSONException ; import org . json . JSONObject ; import android . os . Bundle ; import android . util . Log ; import com . and3 . UnityPlayerNativeActivity ; import com . unity3d . player . * ; public class SDKAPI extends UnityPlayerNativeActivity { private String test ( int a , String b ) { Log . i ( “unity” , “test: “ + a + ” “ + b ) ; JSONObject obj = new JSONObject ( ) ; try { obj . put ( “first” , 43 ) ; obj . put ( “second” , “testCall” ) ; } catch ( JSONException e ) { e . printStackTrace ( ) ; } com . unity3d . player . UnityPlayer . UnitySendMessage ( “ARCamera” , “UnityTest” , obj . toString ( ) ) ; return “wxd” ; } private static int test1 ( int a , String b ) { Log . i ( “unity” , “test1: “ + a + ” “ + b ) ; JSONObject obj = new JSONObject ( ) ; try { obj . put ( “first” , 55 ) ; obj . put ( “second” , “test1Call” ) ; } catch ( JSONException e ) { e . printStackTrace ( ) ; } com . unity3d . player . UnityPlayer . UnitySendMessage ( “ARCamera” , “UnityTest” , obj . toString ( ) ) ; return 6543 ; } } |
这样java里的两个方法就都可以被调用了,那么差别主要包括哪些呢,总共有四点:
1、java里面的类需要继承UnityPlayerNativeActivity;
2、unity里面AndroidJavaClass的参数改为:
1 | _class = new AndroidJavaClass ( “com.unity3d.player.UnityPlayer” ) ; |
3、从刚才得到的class实例中获取currentActivity:
1 | _obj = _class . GetStatic < AndroidJavaObject > ( “currentActivity” ) ; |
4、下面在调用call方法的时候,把之前从AndroidJavaClass实例调用改成从AndroidJavaObject调用。
此外,关于java调用unity的接口比较简单,直接调用com.unity3d.player.UnityPlayer.UnitySendMessage接口就行了。总共包含三个参数,第一个表示unity中包含c#脚本的GameObject实例名称,第二个表示方法名,第三个表示传递的参数,由于只是个字符串类型,所以如果有多个参数需要传递的话,可以像我这样使用JSONObject传递多个参数。