Android与Unity之间数据交互

发表于2017-05-18
评论1 4.3k浏览
在使用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().rotation = Quaternion.Euler (x, y, z);
    }
 
    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项目即可

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论