轉載請注明出處: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到此結束~~
感謝大家支持!如有錯誤,請指出~~
謝謝~
