Android与Unity之间数据交互
发表于2017-05-18
在使用Unity生成Android apk的过程中,难免有需要有Android进行数据交互的场景,
1.譬如在VR场景中,我们需要将手机的传感器数据用Android传递给Unity来作为Camera的方向数据(Unity自身的input系统中是没有这个参数的);
2.在Unity中,我们时常需要完成登录支付等需要调用外部库的情况,这个就需要Unity给Android中传递数据了。
Android给Unity传递数据
我们需要使用Unity的标准数据传递方法:
UnityPlayer.UnitySendMessage(String arg0, String arg1, String arg2);
arg0:数据接收的GameObject对象
arg1:数据接收的方法名
arg2:字符串类型数据
我们可以看到Unity的消息传递只支持String类型,在某些情况下我们需要转换一下。好了,下面我们就以传递方向传感器数据来说明一下Android如何给Unity传递数据。
1.首先,我们在Android IDE (这里使用的是Eclipse)新建一个Android project,如下图,并且load一个重要的来自Unity的库:classes.jar。这个库的位置是:D:UnityEditorDataPlaybackEnginesAndroidPlayerVariationsmonoDevelopmentClassesclasses.jar,不同的Unity版本可能位置稍微有点不同,这个库是专门用于Android与Unity之间传递数据的。

2.MainActivity继承Unity类UnityPlayerActivity,使用UnityPlayer.UnitySendMessage给Unity传递消息,注意删除setContentView方法(这一方法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 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | package com.tencent.sensor; import com.unity3d.player.UnityPlayer; import com.unity3d.player.UnityPlayerActivity; import android.R.xml; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import android.util.Log; public class MainActivity extends UnityPlayerActivity { //继承UnityPlayerActivity private SensorManager mSensorManager; private Sensor mOrientation; public static float x; public static float y; public static float z; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // setContentView(R.layout.activity_main);/*注意删除这个方法,否则会有冲突*/ mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mOrientation = mSensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); mSensorManager.registerListener(new MySensorEventListener(), mOrientation, SensorManager.SENSOR_DELAY_NORMAL); } class MySensorEventListener implements SensorEventListener { @Override public void onSensorChanged(SensorEvent event) { // TODO Auto-generated method stub x = event.values[0]; y = event.values[1]; z = event.values[2]; String msg = String.valueOf(x) + "|" + String.valueOf(y) + "|" + String.valueOf(z);/* 由于Unity只能传递String方法,我们需要转换一下 */ Log.i("java", msg); /** * 我们给Camera这个Gameobjectchuan的message方法传递了参数为msg的消息 */ UnityPlayer.UnitySendMessage( "Camera" , "messgae" , msg); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // TODO Auto-generated method stub } } public void StartActivity(String name){ Intent intent = new Intent(getApplicationContext(),TestActivity. class ); intent.putExtra( "name" , name); this .startActivity(intent); } } |
3.下一步,回到Unity完成message的接收脚本,在这一步我们我们把获取到msg重新处理成float型,然后赋给Camera的rotation,这样就形成了一个简单的VR Camera的头部追踪,但是没有经过任何优化(优化之后再讲)
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 | using UnityEngine; using System.Collections; public class move : MonoBehaviour { float x; float y; float z; public float speed; // Use this for initialization void Start () { } // Update is called once per frame void FixedUpdate () { GetComponent } void messgae( string str) { Debug.Log( "unity" +str); string [] msg = str.Split( '|' ); x = float .Parse(msg [0]); y = float .Parse (msg [1]); z = float .Parse (msg [2]); } } |
4.再完成了所有代码之后,我们需要把Android项目打包成一个jar包,供Unity使用,使用Eclipse打包的过程是:
在选择文件打包时特别需要注意的是,需要把gen文件夹下的文件去掉,并且把libs中的classes.jar去掉,因为Unity编译时会自动包含进classes.jar,重复打包,会有冲突。


-》

5.回到Unity,在project下,新建一个文件夹 Plugins/Android/,把打包好的jar包放入文件路径下的bin/下,并且把除src/ , gen/ 之外的Android文件,全部copy到Plugins/Android/下

6.编译我们的Unity项目,注意Bundle Identifier需要与我们Android项目的包名一致,完成!

Unity给Android传递数据
Android给Unity传递数据已经完成了,那么对于第二类场景,我们如何在Unity中给Android中传递数据呢?
1. 某一部分是复用上面的设置与写法,不同是 这次轮到Android的MainActivity中预置好接收消息的方法了,在之前我们的Android项目中java代码中先写好接收方法,我们希望Unity能传递一个String参数下来并且这时启动一个新的界面来完成一些操作:
1 2 3 4 5 | public void StartActivity(String name){ Intent intent = new Intent(getApplicationContext(),TestActivity. class ); intent.putExtra( "name" , name); this .startActivity(intent); } |
2. 回到Unity,在脚本中,我们利用类似反射的方法来找到java中的方法名,并调用它
1 2 3 | AndroidJavaClass jc = new AndroidJavaClass( "com.tencent.sensor.MainActivity" ); /*这个类名要写全且准确,否则Unity找不到*/ AndroidJavaObject jo = jc.GetStatic "currentActivity" ); /*这个currentActivity指代Unity当前所在的Activity*/ jo.Call( "StartActivity" , "Unity传下来的参数" ); |
3. 编译Unity项目即可