[Unity3D]Unity3D遊戲開發之從Unity3D到Eclipse

來源:互聯網
上載者:User

標籤:utf-8   float   bool   size   cli   縮小   min   task   速度   

       

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

喜歡我的部落格請記住我的名字:秦元培,我的部落格地址是blog.csdn.net/qinyuanpei。

轉載請註明出處,本文秦元培, 本文出處:http://blog.csdn.net/qinyuanpei/article/details/39717795

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


       各位朋友大家好,我是秦元培。歡迎大家關注我的部落格,我的部落格地址是blog.csdn.net/qinyuanpei。首先祝大家能夠度過一個愉快的十一長假。

今天呢,博主將為大家送上Unity-Android系列的最後一篇文章《Unity3D遊戲開發之從Unity3D到Eclipse》。通過前面的學習。大家已經知道通過在Eclipse中為Unity編寫外掛程式的方法,我們能夠實如今Unity與Android API的通訊。但是不幸的是,這樣的方法並不能對全部的Android API奏效,在某些時候,我們須要反客為主,將Unity項目匯出為Android項目,然後在Eclipse中繼續改動遊戲的內容。這樣的方法在《Unity3D遊戲開發之Unity與Android互動調用研究》這篇文章中已經提及,只是並沒有真正地進行過研究。

之前有個叫@SHANlover的朋友問我,能不能寫一篇Unity項目匯出Eclipse的文章,因此博主便抽出時間研究了下這樣的方法。從而有了今天的這篇文章。

首先,我們來建立一個簡單地情境:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWlueXVhbnBlaQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" />

       好了,建立完情境以後我們就能夠直接編寫一個指令碼CubeScripts.cs來控制情境中的Cube:

using UnityEngine;using System.Collections;public class CubeScripts : MonoBehaviour {/// <summary>/// 定義旋轉速度/// </summary>public float RotateSpeed=45;/// <summary>/// 定義攝像機的近期距離/// </summary>private float mNear=2.5F;    /// <summary>/// 攝像機當前距離/// </summary>private float mDistance=5F;/// <summary>/// 定義攝像機的最遠距離/// </summary>private float mFar=7.5F;/// <summary>/// 攝像機的縮放速率/// </summary>private float mZoomRate=0.5F;/// <summary>/// 主攝像機/// </summary>private Transform mCamera;/// <summary>/// 在Start()方法中我們設定了遊戲體的名稱,由於我們在/// Android項目中須要用到這個名稱,同一時候擷取主相機對象/// </summary>void Start () {this.name="Main Cube";mCamera=Camera.main.transform;}/// <summary>/// 在Update()方法中我們讓Cube依照一定的速度進行旋轉/// </summary>void Update () {transform.Rotate(Vector3.up * Time.deltaTime * RotateSpeed);}/// <summary>/// 定義一個放大的方法供外部調用/// </summary>public void ZoomIn(){mDistance-=mZoomRate;mDistance=Mathf.Clamp(mDistance,mNear,mFar);mCamera.position=mCamera.rotation * new Vector3(0,0,-mDistance)+transform.position;}/// <summary>/// 定義一個縮小的方法供外部調用/// </summary>public void ZoomOut(){mDistance+=mZoomRate;mDistance=Mathf.Clamp(mDistance,mNear,mFar);mCamera.position=mCamera.rotation * new Vector3(0,0,-mDistance)+transform.position;}}
這段指令碼十分地簡單。沒有什麼可說的,在這裡我們定義了兩個方法ZoomIn和ZoomOut。這兩個方法我們將提供給Android來調用。

我們將這段指令碼綁定到Main Cube這個對象上。接下來,我們將項目Build一下,這裡我們將項目的PackageName設為com.android.unity2eclipse,然後將其匯出為一個Android項目:


          那麼。這樣我們就得到一個能夠在Eclipse中開啟的Android項目。

但是這個Android項目我們怎麼樣使用呢?在金曾璽老師《Unity3D手機遊戲開發》一書中是將Unity匯出的Android項目作為一個庫,然後再用一個新的Android項目去調用這個庫。這本書中所使用的Unity版本號碼是4.X,而博主所使用的Unity版本號碼是4.5.1。最初博主就是依照這樣的思路去編寫Android程式,但是在經曆了無數次的失敗後。博主開始懷疑這樣的方法的正確性。帶著嘗試的念頭,博主直接執行了由Unity匯出的Android項目。結果程式成功地在手機上執行了。


       那麼。接下來我們最好還是冷靜地分析下從Unity匯出的這個Android項目,我們能夠看到整個項目的目錄結構是這樣的:


在這個目錄結構中,我們能夠看到它是一個標準的Android項目。在libs中的unity-class.jar就是我們在前面的文章中所使用過的jar庫檔案。而在assets目錄中我們能夠看到Unity所依賴的dll檔案。在com.android.unity2eclipse這個Package中。我們會發現一個名為UnityPlayerNativeActivity.class的類,該類定義例如以下:

package com.android.unity2ecplise;import com.unity3d.player.*;import android.app.NativeActivity;import android.content.res.Configuration;import android.graphics.PixelFormat;import android.os.Bundle;import android.view.KeyEvent;import android.view.MotionEvent;import android.view.Window;import android.view.WindowManager;public class UnityPlayerNativeActivity extends NativeActivity{protected UnityPlayer mUnityPlayer;// don‘t change the name of this variable; referenced from native code// Setup activity layout@Override protected void onCreate (Bundle savedInstanceState){requestWindowFeature(Window.FEATURE_NO_TITLE);super.onCreate(savedInstanceState);getWindow().takeSurface(null);setTheme(android.R.style.Theme_NoTitleBar_Fullscreen);getWindow().setFormat(PixelFormat.RGB_565);mUnityPlayer = new UnityPlayer(this);if (mUnityPlayer.getSettings ().getBoolean ("hide_status_bar", true))getWindow ().setFlags (WindowManager.LayoutParams.FLAG_FULLSCREEN,                       WindowManager.LayoutParams.FLAG_FULLSCREEN);setContentView(mUnityPlayer);mUnityPlayer.requestFocus();}// Quit Unity@Override protected void onDestroy (){mUnityPlayer.quit();super.onDestroy();}// Pause Unity@Override protected void onPause(){super.onPause();mUnityPlayer.pause();}// Resume Unity@Override protected void onResume(){super.onResume();mUnityPlayer.resume();}// This ensures the layout will be correct.@Override public void onConfigurationChanged(Configuration newConfig){super.onConfigurationChanged(newConfig);mUnityPlayer.configurationChanged(newConfig);}// Notify Unity of the focus change.@Override public void onWindowFocusChanged(boolean hasFocus){super.onWindowFocusChanged(hasFocus);mUnityPlayer.windowFocusChanged(hasFocus);}// For some reason the multiple keyevent type is not supported by the ndk.// Force event injection by overriding dispatchKeyEvent().@Override public boolean dispatchKeyEvent(KeyEvent event){if (event.getAction() == KeyEvent.ACTION_MULTIPLE)return mUnityPlayer.injectEvent(event);return super.dispatchKeyEvent(event);}// Pass any events not handled by (unfocused) views straight to UnityPlayer@Override public boolean onKeyUp(int keyCode, KeyEvent event)     { return mUnityPlayer.injectEvent(event); }@Override public boolean onKeyDown(int keyCode, KeyEvent event)   { return mUnityPlayer.injectEvent(event); }@Override public boolean onTouchEvent(MotionEvent event)          { return mUnityPlayer.injectEvent(event); }/*API12*/ public boolean onGenericMotionEvent(MotionEvent event)  { return mUnityPlayer.injectEvent(event); }}
相信大多數看過我部落格的人都會認為這個類有點眼熟吧。不錯,在之前的《Unity3D遊戲開發之在Android視圖中嵌入Unity視圖》這篇文章中,我們就是利用這個類實現了在Android視圖中嵌入Unity視圖,僅僅只是當時這個類是定義在Unity的unity-class.jar這個庫中的,而更為確切地位置是在com.unity3d.player這個包以下的UnityPlayerNativeActivity類,我們注意到此時這個類是繼承自NativeActivity的,在前面的文章中博主以前提及這個類,它是Android提供給C/C++開發人員的介面。

換句話說。Unity項目在Android平台上內部依靠的實際上就是NativeActivity介面,僅僅只是Unity自己使用的介面是封裝過的。而我們這裡使用的介面是直接繼承自父類。那麼,我們在這一刻就會產生疑問。從這個類從詳細實現上來講基本的功能就是對Activity進行初始化,那麼我們在Activity中能夠看到什麼由誰來決定呢?大家注意到這裡有一個SetContentView()的方法。它傳入了UnityPlayer類型的參數作為Activity顯示的內容。相信從如今開始,大家對Unity提供的Android介面的認識會越來越清晰吧。

為了驗證我們的想法,接下來。我們來建立一個布局檔案activity_main。它的代碼定義例如以下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context=".MainActivity" >    <Button        android:id="@+id/BtnZoomIn"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentTop="true"        android:text="@string/ZoomIn" />    <LinearLayout          android:id="@+id/UnityView"          android:layout_width="match_parent"          android:layout_height="match_parent"          android:layout_above="@+id/BtnZoomOut"          android:layout_below="@+id/BtnZoomIn"          android:orientation="vertical" >      </LinearLayout>    <Button        android:id="@+id/BtnZoomOut"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:text="@string/ZoomOut" /></RelativeLayout>
接下來,我們建立與之相應的Java類檔案MainActivity.class:

package com.android.unity2ecplise;import com.android.unity2ecplise.R;import com.unity3d.player.UnityPlayer;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.LinearLayout;/*我們這裡讓我們定義的MainActivity繼承自Unity匯出項目中的UnityPlayerNativeActivity*/public class MainActivity extends UnityPlayerNativeActivity {private Button BtnZoomIn,BtnZoomOut;@Override protected void onCreate (Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);//擷取顯示Unity視圖的父控制項LinearLayout mParent=(LinearLayout)findViewById(R.id.UnityView);//擷取Unity視圖View mView=mUnityPlayer.getView();//將Unity視圖加入到Android視圖中mParent.addView(mView);//放大BtnZoomIn=(Button)findViewById(R.id.BtnZoomIn);BtnZoomIn.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View arg0) {UnityPlayer.UnitySendMessage("Main Cube","ZoomIn","");}});//縮小BtnZoomOut=(Button)findViewById(R.id.BtnZoomOut);BtnZoomOut.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View arg0) {UnityPlayer.UnitySendMessage("Main Cube","ZoomOut","");}});}}
在這段代碼中。我們通過UnitySendMessage調用了Unity中定義的兩個方法ZoomIn、ZoomOut。好了,接下來。我們改動設定檔,使主Activity相應於MainActivity類,開啟
AndroidManifest.xml檔案:

<?

xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.unity2ecplise" android:theme="@android:style/Theme.NoTitleBar" android:versionName="1.0" android:versionCode="1" android:installLocation="preferExternal"> <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" android:anyDensity="true" /> <application android:icon="@drawable/app_icon" android:label="@string/app_name" android:debuggable="false"> <activity android:label="@string/app_name" android:screenOrientation="fullSensor" android:launchMode="singleTask" android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|orientation|screenLayout|uiMode|screenSize|smallestScreenSize|fontScale" android:name="com.android.unity2ecplise.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <meta-data android:name="unityplayer.UnityActivity" android:value="true" /> <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" /> </activity> </application> <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="17" /> <uses-feature android:glEsVersion="0x00020000" /></manifest>

如我們所推測的那樣。acivity節點的name屬性相應於com.android.unity2ecplise.UnityPlayerNativeActivity。這說明在此之前,Android是以這個類作為主Acivity。

如今我們將其改為我們自訂的類。這樣我們就能使用自訂的布局。同一時候大家會注意到以下這兩行:

      <meta-data android:name="unityplayer.UnityActivity" android:value="true" />      <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" />
之前我們在講Unity視圖嵌入Android視圖時以前碰到過Android視圖無法取得焦點的問題,當時就是在設定檔裡加入了這樣兩行代碼,此時此刻,大家是不是和博主一樣有種大徹大悟的感覺呢。我們執行程式,會發現介面像我們所希望看到的那樣被改變了。並且我們能夠通過兩個button來改變視圖中立方體的大小:



watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcWlueXVhbnBlaQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" />

這樣我們就能夠認識到從Unity中匯出的就是Android項目。我們能夠直接將其改動來達到滿足我們要求的目的。至於金曾璽老師的這樣的方法。在官方API文檔中的確有提到過這樣的方法,只是博主嘗試了好久,這樣的方法都失敗了,不知道是不是由於Unity在新版本號碼中已經攻克了這個問題,從而能夠直接匯出可執行檔Android項目。

        最後來說說網路上流傳的一種方法。據說在Unity中將項目Build下就會在project目錄下的Temp目錄下產生一個名為StagingArea目錄。我們將這個目錄在匯入到Eclipse中並將其設為一個庫,然後在建立的Android項目中引用這個庫。並將這個項目中的assets目錄覆蓋建立項目中的assets目錄,然後我們僅僅要讓主Acitivity繼承Unity提供的Android介面中的UnityPlayerActivity就可以。這樣的方法博主並沒有去嘗試,只是在Build的時候確實會產生這樣一個目錄。只是博主認為這樣是不是有點麻煩了啊,既然Unity匯出的Android項目直接就能用。我們何必要再去用這樣的複雜的方法呢,只是我認為大致的思路就是這樣的,UnityPlayerActivity負責Acivity生命週期的維護。UnityPlayer負責渲染Unity情境中的內容,而我們在Unity中使用的資源都被Unity的引擎在內部進行了處理,總之把握了這些,Unity和Android的互動就基本沒什麼問題了。好了,謝謝大家關注我的部落格,今天的內容就是這樣了,希望大家喜歡。


每日箴言:有些路看起來非常近,但是走下去卻非常遠的。缺少耐心的人永遠走不到頭。人生,一半是現實,一半是夢想。 ——顧城




-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

喜歡我的部落格請記住我的名字:秦元培。我的部落格地址是blog.csdn.net/qinyuanpei。

轉載請註明出處。本文秦元培, 本文出處:http://blog.csdn.net/qinyuanpei/article/details/39717795

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


本文源碼下載:Unity項目 Android項目


[Unity3D]Unity3D遊戲開發之從Unity3D到Eclipse

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.