zoukankan      html  css  js  c++  java
  • 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到此结束~~ 
    感谢大家支持!如有错误,请指出~~ 
    谢谢~

  • 相关阅读:
    古谚、评论与论断、名篇与名言
    重读《西游记》
    重读《西游记》
    命名之法 —— 时间、季节、地点
    命名之法 —— 时间、季节、地点
    文言的理解 —— 古时的称谓、别称、别名
    文言的理解 —— 古时的称谓、别称、别名
    Oracle GoldenGate for Oracle 11g to PostgreSQL 9.2.4 Configuration
    瀑布 敏捷 文档
    POJ 1325 ZOJ 1364 最小覆盖点集
  • 原文地址:https://www.cnblogs.com/android-blogs/p/6381789.html
Copyright © 2011-2022 走看看