位置: 編程技術 - 正文
推薦整理分享Unity3D游戲開發(fā)之在Android視圖中嵌入Unity視圖(Unity3D游戲開發(fā)標準教程),希望有所幫助,僅作參考,歡迎閱讀內容。
文章相關熱門搜索詞:Unity3D游戲開發(fā)基礎,Unity3D游戲開發(fā)(第2版),Unity3D游戲開發(fā)引擎,Unity3D游戲開發(fā)標準教程,Unity3D游戲開發(fā)標準教程,Unity3D游戲開發(fā)畢業(yè)論文,Unity3D游戲開發(fā)標準教程,unity3D游戲開發(fā),內容如對您有幫助,希望把文章鏈接給更多的朋友!
轉載自: 今天我們繼續(xù)來研究Unity在Android平臺上的擴展,通過昨天的學習,大家已經知道Unity和Android是可以互相調用的,可是相信大家從昨天的文章中可以看出,如果單純地從調用Android接口的角度來看,我們已經可以實現這一目的??墒菑膶嶋H開發(fā)的角度來看,我們只是邁出了很小的一步。為什么這么說呢,因為在實際的開發(fā)中可能我們不僅需要從接口上實現與Unity的對接,而且需要從界面上實現與Unity的對接。比如,現在主流的網游都會在游戲開始的時候給玩家一個選擇創(chuàng)建角色的過程,通常界面上會顯示各種類型的角色設定,玩家可以通過界面了解每種類型的角色的特點,從而選擇合適自己的角色。從技術上來講,這一部分我們可以完全使用Unity3D的GUI系統(tǒng)來實現,不過本文的目的在于探討Unity和Android的對接問題,因此我們可以假定Android在整個對接過程中扮演著界面渲染的角色,而Unity則負責游戲邏輯的維護。那么,這樣就誕生了我們今天的問題,能不能將Unity作為Android界面的一部分嵌入到Android應用中呢?答案當然是肯定的。
一、為Unity編寫Android插件
首先,我們來看Unity中為Android提供的類文件UnityPlayerNativeActivity.java,該文件位于如下位置:
D:ProgramFilesUnityEditorDataPlaybackEnginesandroidplayercomunity3dplayer(在不同的計算機上可能會有所不同,大家靈活運用即可)
[java] view plaincopyprint?package 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.View; 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_); 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); } /*API*/ public boolean onGenericMotionEvent(MotionEvent event) { return mUnityPlayer.injectEvent(event); } } 熟悉Android開發(fā)的朋友一定對這個類覺得熟吧,NativeActivity是Google在Android3.0后推出的,其目的是為了讓開發(fā)者使用C/C在NDK環(huán)境下管理Activity的生存周期,于是我們可以大膽的猜測Unity之所以可以和Android進行交互是因為NDK提供了方便之門,果然,博主在Unity的目錄下找到了libmain.so、libunity.so、libmono.so這三個文件,這證實我們的猜想是正確的。在這個類中,我們可以看到Unity做了大量的初始化工作,并且重寫了NativeActvity的相關方法。不知道大家還記不記得我們在前一篇文章中定義主Activity時,我們是讓它繼承自UnityPlayerActivity而不是Android的Activity。那么,這個UnityPlayerActivity是什么呢?我們打開它的文件:[java] view plaincopyprint?package com.unity3d.player; /** * @deprecated Use UnityPlayerNativeActivity instead. */ public class UnityPlayerActivity extends UnityPlayerNativeActivity { } 這時候我相信大家和博主一樣都有一種恍然大悟的感覺,原來它是繼承自UnityPlayerNativeActivity的,換句話說Unity在Android這部分其實做了兩件事,即初始化Activity和重寫相關的方法。我們注意到代碼中的注釋提示這個類已經deprecated建議我們使用UnityPlayerNativeActivity,這點我們暫時不用管,我們依然使用UnityPlayerActivity,因為它和UnityPlayerNativeActivity本質上是一樣的。好了,到目前為止,如果大家已經理解了這里所有的內容,那么我們可以浩浩蕩蕩地沖向Eclipse開始編寫Android項目了。
和昨天一樣,我們創(chuàng)建一個Android項目并將其設為庫,這里我們將其包名設為com.android.unityview4android。這個名稱很重要,我們在Unity中將繼續(xù)使用這個名字。首先我們來創(chuàng)建一個Android的布局文件activity_main.xml:
[html] view plaincopyprint?<RelativeLayout xmlns:android=" xmlns:tools=" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <Button android:id="@id/BtnPre" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:text="@string/BtnPre" /> <LinearLayout android:id="@id/UnityView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@id/BtnNext" android:layout_below="@id/BtnPre" android:orientation="vertical" > </LinearLayout> <Button android:id="@id/BtnNext" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:text="@string/BtnNext" /> </RelativeLayout>這里我們放置了兩個Button按鈕,分別用來控制Unity向前、向后切換模型,在屏幕中間有一個叫做UnityView的線性布局,它將作為Unity視圖的父控件,即我們會將Unity的視圖放到這個控件里。我們注意到在UnityPlayerNativeActivity.java類中有一個UnityPlayer類型的變量mUnityPlayer,該類型博主目前沒有找到官方的相關說明,博主推測它應該是負責Unity界面渲染的一個類吧,在這個類中有一個getView()方法,它將返回一個View類型的,我們便可以通過這種方法將其添加到Android視圖里,因為我們已經準備好了一個UnityView的父控件,所以這一切實現起來變得相當地容易:
[java] view plaincopyprint?package com.android.unityview4android; /*導入Unity提供的類*/ import com.unity3d.player.UnityPlayer; import com.unity3d.player.UnityPlayerActivity; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.LinearLayout; public class MainActivity extends UnityPlayerActivity { private Button BtnPre,BtnNext; @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); //上一個 BtnPre=(Button)findViewById(R.id.BtnPre); BtnPre.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { UnityPlayer.UnitySendMessage("GameObject", "ShowPrevious", ""); } }); //下一個 BtnNext=(Button)findViewById(R.id.BtnNext); BtnNext.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { UnityPlayer.UnitySendMessage("GameObject", "ShowNext", ""); } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } } 好了,這樣我們就完成了Jar庫的編寫,我們只要將Jar庫導入到Unity中,并且按照上一篇文章中所述的方法構建Android插件目錄組織相關資源就可以了。最后我們給出AndroidManifest.xml文件:[html] view plaincopyprint?<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android=" package="com.android.unityview4android" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.android.unityview4android.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 二、創(chuàng)建Unity項目 好了,現在我們來創(chuàng)建Unity項目,我們這里創(chuàng)建一個簡單地場景,場景中只有一個空游戲體和攝像機,我們將通過腳本的形式來控制Unity渲染,主要的腳本代碼如下:[csharp] view plaincopyprint?using UnityEngine; using System.Collections; public class ModelManager : MonoBehaviour { //模型 public GameObject[] Models; //當前索引 private int index=0; //當前對象 private GameObject mObject; void Start () { this.name="GameObject"; //生成第一個物體 mObject=(GameObject)Instantiate(Models[index]); } public void ShowNext() { //使索引增加 index=1; //范圍控制 if(index>Models.Length-1){ index=0; } //銷毀原來物體 Destroy(mObject); //生成新物體 mObject=(GameObject)Instantiate(Models[index]); } public void ShowPrevious() { //使索引減少 index-=1; //范圍控制 if(index<0){ index=Models.Length-1; } //銷毀原來物體 Destroy(mObject); //生成新物體 mObject=(GameObject)Instantiate(Models[index]); } } 這段腳本我們綁定到這個空的游戲體上,腳本的兩個方法ShowNext()和ShowPrevious()相對應,通過UnitySendMessage()實現通信。好了,我們來運行項目,如圖所示:我們可以注意到當程序打開的那一瞬間,是Android視圖先加載、然后Unity視圖才加載的,給人整體的感覺就是在Activity里面嵌套了一個Activity??墒遣┲黢R上就發(fā)現了一個問題,這Android視圖中的按鈕無法取得焦點啊,點擊事件無效。這是為什么呢?后來博主找到的解決方法是在AndroidManifest.xml文件中的activity子節(jié)點下增加如下兩行代碼:
[csharp] view plaincopyprint?<meta-data android:name="android.app.lib_name" android:value="unity" /> <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" /> 這樣問題是解決了,可是我們得搞懂為什么吧,在Unity官方文檔中,我們找到了答案:請注意,NativeActivity在Android2.3以后被引入而且不支持該版本以下的設備。因為觸摸/運動事件處理在本機代碼,Java視圖通常不會看到這些事件。然而,在統(tǒng)一轉發(fā)機制允許將事件傳播到DalvikVM。為了使用這個機制,您需要修改manifest文件如下:
[html] view plaincopyprint?<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android=" package="com.company.product"> <application android:icon="@drawable/app_icon" android:label="@string/app_name"> <activity android:name=".OverrideExampleNative" android:label="@string/app_name"> <meta-data android:name="android.app.lib_name" android:value="unity" /> <meta-data android:name="unityplayer.ForwardNativeEventsToDalvik" android:value="true" /> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 這段話的意思就是說Android的事件是運行在本機代碼中的,Java視圖是看不到這些事件的,然而我們可以通過Unity提供的統(tǒng)一轉發(fā)機制將這些事件發(fā)送到Android虛擬機,為了使用這個機制,我們必須修改Android的AndroidManifest.xml文件。博主感覺Android插件這塊官方目前做得不是很好,總是給人一種云里霧里的感覺,而且通過各種語言相互調用增加了調試的難度,關于Android更多的內容,大家可以參考官方的文檔:點擊這里.好了,今天的內容就是這樣啦,希望大家喜歡。最后再來看看程序運行的效果吧UnityRandom介紹 介紹UnityRandom是一個針對Unity3D的偽隨機數庫,使用C#語言開發(fā)。代碼和文檔都在Github上。UnityRandom采用Mersennetwister偽隨機數發(fā)生算法,能夠快速產生高質
游戲簡單控制邏輯 一個輕量級的狀態(tài)機 ??出處:
三分鐘了解LOD在游戲里面的運用 性能優(yōu)化
友情鏈接: 武漢網站建設