• Android与Unity交互研究


    转载请注明出处:http://blog.csdn.net/crazy1235/article/details/46733221

    unity与android交互的由来

    本人在项目开发过程中,遇到这样一个需求,把unity的场景放到Android中去显示。刚开始做的时候也是一头雾水,unity是什么东西都没听说过。后来也是查询很多资料,才实现了需求的效果。所以把自己的一些总结记录于此,方便各位同行参考。


    unity简单介绍

    unity是可以开发诸如三维视频游戏、建筑模型、三维动画等交互类内容的多平台综合游戏开发工具,具有很强大的跨平台性。在unity之中编写好场景和程序之后,可以导出Android、iOS、windows phone、PC等多个平台的版本。

    图片名称 图片名称

    如上图,列出了unity可以导出的所有平台。


    unity与android交互介绍

    一般的都是,把unity作为android程序中的一部分,将一个u3d场景当成一个界面或者一个界面的一部分。 
    还有的是把android作为unity的一部分进行开发。不过这种形式的开发很少,也没必要。

    我们下面以一个例子来介绍二者之间的交互。

    首先,在unity中搞了一个游戏场景,运行之后如下图:

    图片名称

    此场景中“1”是一个label,用来显示从android中设置的怪兽人物的名称。“2”用于在android程序中控制大小显示变化的。“3”是用与unity中测试大小变化的。

    unity调用android的方法

    我们需要在运行起来Unity引擎之后,调用Java类中的方法获取怪兽的姓名,就需要Uniy调用Android的方法。 
    unity调用java方法一共有四种形式,分别是:

    • 没有返回值的普通方法
    AndroidJavaObject jo = new AndroidJavaObject("android.content.res.Configuration");
    jo.Call("setToDefaults");
    • 带有返回值的普通方法
    AndroidJavaObject jo = new AndroidJavaObject("java.lang.String", "some string");
    int hash = jo.Call<int>("hashCode");
    • 没有返回值的静态方法
    AndroidJavaObject jo = new AndroidJavaObject("android.os.Binder");
    jo.CallStatic("flushPendingCommands");
    • 带有返回值的静态方法
    AndroidJavaObject jo = new AndroidJavaObject("java.lang.String");
    string valueString = jo.CallStatic<string>("valueOf", 42.0);

    我们往游戏对象上绑定一些操作–Operate.cs :

    using UnityEngine;
    using System.Collections;
    public class Operate : MonoBehaviour {
    public Transform target;
    public UILabel label;
    public bool flag = true;
    /// <summary>
    /// 定义旋转速度
    /// </summary>
    public float RotateSpeed=45;
    // Use this for in  itialization
    void Start () {
     //Debug.Log("hello");
     this.name = "Manager";
     GetData ();
    }
    /// <summary>
    /// 通过调用android中的方法获取name,并为label赋值
    /// </summary>
    void GetData(){
     AndroidJavaClass jc = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
     AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject> ("currentActivity");  
     string name = jo.Call <string>("getName", "成功调用android方法");
     label.text = name;
    }
    
    // Update is called once per frame
    void Update () {
     //target.Rotate (Vector3.up * Time.deltaTime * RotateSpeed);
    }
    void OnClick(){
      Screen.orientation = ScreenOrientation.Landscape;
      if (flag) {
        target.localScale = new Vector3 (0.5f, 0.5f, 0.5f);
        flag = false;
        //label.text = "123456";
       } else {
           target.localScale = new Vector3 (0.75f, 0.75f, 0.75f);
           flag = true;
           //label.text = "000000";
       }
     }
     /// <summary>
     /// 顶掉之前的scene
     /// </summary>
    void Unload(){
        Application.LoadLevel (1);
        AndroidJavaClass jc = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");
        AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject> ("currentActivity");  
        jo.Call ("makePauseUnity");
     }
    
    /// <summary>
    /// 放大
    /// </summary>
    void ZoomIn(){
        target.localScale = new Vector3 (0.75f, 0.75f, 0.75f);
    }
    
    /// <summary>
    /// 缩小
    /// </summary>
    void ZoomOut(){
        target.localScale = new Vector3 (0.5f, 0.5f, 0.5f);
    }
    }

    代码和场景编写好之后,就可以使用unity到处apk文件运行了。不过我们需要在eclipse中进行二次开发,所以需要到处android工程。

    在导出的时候,可以选择导出”Google Android Project”。

    图片名称

    如上图,如果不勾选此选项,则导出的是一个apk文件。 
    在导出android工程或apk之前,需要在”Player Settings”进行一些配置:

    图片名称

    图片名称

    这些配置与我们在eclipse等工具进行开发设置的基本一致。 
    导出android工程之后,看到目录结构如下:

    这里写图片描述

    • assets文件下面是unity的一些资源文件,包括场景和渲染的文件。
    • libs下面当然就是jar包和so文件了。
    • src下面包含三个java类。建议使用UnityPlayerActivity.java

    打开UnityPlayerActivity之后,会发现里面有一个对象时UnityPlayer的实例,我们做android中嵌套U3D场景的时候,就是把这个实例当成一个view添加到我们的布局中


    导出android工程之后,会出现两种情况:

    • 你已经有android工程了,此时只需要把assets的文件和libs的包拷贝到你的项目中去,在把需要配置的类在AndroidManifest.xml中配置一下。
    • 没有工程,那么只需要把unity导出的工程导入你的IDE中即可。

    看一下MainActivity的布局:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#E0EEE0"
        android:gravity="center_horizontal"
        android:orientation="vertical" >
    
        <!-- 3D视图区域 -->
    
        <LinearLayout
            android:id="@+id/u3d_layout"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:background="#a6a9af"
            android:orientation="vertical" >
        </LinearLayout>
    
        <!-- 放大 -->
    
        <Button
            android:id="@+id/zoom_in_btn"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:padding="10dp"
            android:text="放大" />
    
        <!-- 缩小 -->
    
        <Button
            android:id="@+id/zoom_out_btn"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:padding="10dp"
            android:text="缩小" />
    
        <!-- 全屏 -->
    
        <Button
            android:id="@+id/u3d_fullscreen_btn"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:padding="10dp"
            android:text="全屏" />
    
    </LinearLayout>

    贴上逻辑代码之前,先介绍一下Android调用unity方法的方式:

    android调用untiy的方法:

    UnityPlayer.UnitySendMessage("Manager", "ZoomIn", "");

    第一个参数是Game Object对象,所以需要在游戏对象上绑定脚本,第二个参数是unity中定义的方法名,第三个参数是定义方法的参数(可空)。

    图片名称

    既可以在定义场景的时候将游戏对象改名字,也可以在代码中设置:

    void Start () {
      this.name = "Manager";
      GetData ();
     }

    在unity中运行之后,就会发现出现一个”Manager”的游戏场景了。

    这里写图片描述

    下面看一下activity的代码:

    package com.jacksen.unity2android;
    import com.unity3d.player.UnityPlayer;
    import android.os.Bundle;
    import android.view.KeyEvent;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.LinearLayout;
    import android.widget.Toast;
    public class MainActivity extends UnityPlayerActivity {
     private LinearLayout u3dLayout;
     private Button zoomInBtn, zoomOutBtn;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      u3dLayout = (LinearLayout) findViewById(R.id.u3d_layout);
      u3dLayout.addView(mUnityPlayer);
      mUnityPlayer.requestFocus();
      zoomInBtn = (Button) findViewById(R.id.zoom_in_btn);
      zoomOutBtn = (Button) findViewById(R.id.zoom_out_btn);
      zoomInBtn.setOnClickListener(new OnClickListener() {
       @Override
       public void onClick(View v) {
        UnityPlayer.UnitySendMessage("Manager", "ZoomIn", "");
       }
      });
      zoomOutBtn.setOnClickListener(new OnClickListener() {
       @Override
       public void onClick(View v) {
        UnityPlayer.UnitySendMessage("Manager", "ZoomOut", "");
       }
      });
     }
     public String getName(final String str) {
      runOnUiThread(new Runnable() {
       @Override
       public void run() {
        Toast.makeText(MainActivity.this, str, 1000).show();
       }
      });
      return "我是怪兽,哈哈哈";
     }
     /**
      * 3D调用此方法,用于退出3D
      */
     public void makePauseUnity() {
      runOnUiThread(new Runnable() {
       @Override
       public void run() {
        if (mUnityPlayer != null) {
         try {
          mUnityPlayer.quit();
         } catch (Exception e) {
          e.printStackTrace();
         }
        }
        MainActivity.this.finish();
       }
      });
     }
     /**
      * 按键点击事件
      */
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
      if (keyCode == KeyEvent.KEYCODE_BACK) {
       onDestroy();
      }
      return true;
     }
     @Override
     protected void onDestroy() {
      super.onDestroy();
      //UnityPlayer.UnitySendMessage("Manager", "Unload", "");
       mUnityPlayer.quit();
     }
     // Pause Unity
     @Override
     protected void onPause() {
      super.onPause();
      mUnityPlayer.pause();
     }
     // Resume Unity
     @Override
     protected void onResume() {
      super.onResume();
      mUnityPlayer.resume();
     }
     @Override
     public void onBackPressed() {
      super.onBackPressed();
      // mUnityPlayer.quit();
      // this.finish();
     }
    }

    OK,运行效果如下:

    图片名称

    跳转到MainActivity之后,unity场景启动,调用android中的getName()方法为怪兽头上的label赋值。 
    点击放大后缩小按钮分别调用Unity中的ZoomIn()和ZoomOut()方法,控制怪兽变大变小。

    OK,至此unity与android的简单交互叙述完毕。


    此篇blog到此结束~~ 
    感谢大家支持!如有错误,请指出~~ 
    谢谢~

  • 相关阅读:
    杭电OJ-1031_Design T-Shirt
    杭电OJ-1036_Average is not Fast Enough!
    2019杭电多校一 L. Sequence (NTT)
    Binary Table CodeForces
    2019牛客多校一 H. XOR (线性基)
    Jzzhu and Numbers CodeForces
    Geometers Anonymous Club CodeForces
    [笔记] 扩展卢卡斯
    Luogu P2183 [国家集训队]礼物 扩展卢卡斯+组合数
    Luogu P4901 排队 fib数列+树状数组+倍增
  • 原文地址:https://www.cnblogs.com/android-blogs/p/6381789.html
Copyright © 2020-2023  润新知