Unity3D遊戲開發之“重寫Unity Android Splash,實現啟動無黑屏”
轉自:http://www.manew.com/thread-98428-1-1.html
Splash設定相信搞unity的朋友都知道這個東西,就是遊戲啟動的時候的啟動畫面,在unity中如果不設定splash的話我們就能夠看到unity遊戲啟動的時候就會出現一張unity預設的帶有Unity標誌的splash啟動頁,如果我們需要換成自己的啟動頁就需要在打包的時候把splash設定成自己的圖片。
那麼Unity為什麼會有啟動頁這麼一個東西呢?
其實在我們遊戲啟動的時候unity或者我們自己會有一系列的資源載入或者初始化的東西,而這些操作都需要時間來完成,如果沒有splash的話就會造成一種卡機的假象。當unity所有的初始化都完成並載入第一個場景完成,unity就會自動的隱藏splash。
那麼可能有很多朋友就有疑問了,既然unity自帶了splash的設定我們為什麼還要重寫splash呢?
答案:不知道大家有沒有注意到,在我們啟動unity遊戲的時候會出現一段時間的黑屏然後才出現我們設定好的splash,如果機器配置越差,黑屏時間就越長。為了解決這個黑屏時間,我們重寫了splash功能,讓我們遊戲一啟動就出現我們的splash啟動頁。
接下來我們說一說重寫splash的流程:
重寫splash會涉及到好4個流程,1、編寫JAVA層splash載入和處理程式碼 2、設定Unity中的splash 3、編寫unity層隱藏splash程式碼 4、splash圖片資源路徑設定
1、編寫JAVA層splash載入和處理程式碼
在這一流程中我們首先需要編寫我們自己的程式啟動Activity,此Activity繼承UnityPlayerActivity,因為我們需要在主Activity onCreate()的時候顯示我們JAVA層的splash。
再寫一個專門管理splash載入、顯示和隱藏的類。這個類的職責就是負責splash的載入、顯示、隱藏。
在載入了splash圖片新建view後我們需要把他加到Unity的View中,並且設定我們新建view的長寬為我們的Unity檢視的長寬這樣才能保證我們載入的splash跟unity中設定的splash一樣而不會變形。
2、設定Unity中的splash
這個過程是必要的,因為unity載入第一個場景的時候是需要時間的,而這段時間unity會使用splash來進行覆蓋,而且還會涉及到隱藏splash時機的
3、編寫unity層隱藏splash程式碼
第二點說了一下隱藏時機的問題,可能大部分人都會認為unity splash消失後才會執行啟動場景中的Awake。但是我很確定的告訴你,並不是你想想的那樣。
其實在Awake執行後splash才會消失,而這段時間是不可預估的,所以如果我們不設定Unity自帶的splash頁面就會造成我們無法知道的splash什麼時候去隱藏他。
所以設定了unity的自帶splash後我們就能光明正大的把隱藏的程式碼放到啟動場景的Awake中去執行了。
4、splash圖片資源路徑設定
如果明白了上面的思路,那麼最後一步就是設定我們的splash資源路徑了。而這一步我們要設定2個地方的資源,一個是Android層載入的splash的位置,一個是Unity層設定的splash的位置。
可能你要問,unity層的splash設定不就是直接把圖片拖到設定面板中麼,但是這次我們不這樣做,其實搞懂了unity設定的splash最後在Android包中哪個位置那麼你就瞭解我要怎麼做了。
注意:splash圖片必須是png圖片並且名字是splash.png
Android層的splash設定:放入Assets\Plugins\Android\res\drawable中
Unity層的splash設定:放入Assets\Plugins\Android\assets\bin\Data中,不需要再設定面板中去設定splash,所以大家明白了unity設定的splash最後就是在assets\bin\Data中。
一般Android層和unity層的splash應該是同一張圖片,當然你也可以不一樣。
有朋友推薦了一篇部落格:http://blog.csdn.net/u012169685/article/details/52068809我抽空看了一下他的做法,基本的做法沒有什麼區別,最大的區別是我增加了一步就是設定unity的自身啟屏頁。我來解釋一下為什麼要這麼做。
在上面部落格的程式碼中我們可以看到最後他隱藏splsh的程式碼是在start裡面Invoke("OnFinish", 0.5f),這就說明他延遲了0.5s來隱藏splash,但是我很明確的是他這個做法是不準確的,因為unity隱藏splash的時機是不確定的,這種做法會導致splash提前或者延後隱藏,這完全取決於機器的效能。
我的做法是在啟動場景awake之前是靠Android層的splash覆蓋unitysplash,Awake之後就是顯示的unity自己的splash,最後隱藏是unity的自身行為,這種方式保證了unity的百分百準確隱藏splash。
例項程式碼:
package com.zwwx.jsws;
import com.unity3d.player.UnityPlayer;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
public class Splash extends SDKBase{
private ImageView bgView = null;
private UnityPlayer mUnityPlayer = null;
private static Splash mInstance;
public static Splash getInstance() {
if (null == mInstance) {
synchronized (Splash.class) {
if (null == mInstance) {
mInstance = new Splash();
}
}
}
return mInstance;
}
@Override
public void onCreate(Activity activity, Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(activity, savedInstanceState);
mUnityPlayer = ((ZWWXActivity)mActivity).getUnityPlayer();
onShowSplash();
}
@Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
onHideSplash();
}
@SuppressLint("NewApi")
public void onShowSplash() {
if (bgView != null)
return;
try {Resources r = UnityPlayer.currentActivity.getResources();
bgView = new ImageView(UnityPlayer.currentActivity);
int splash_bg = r.getIdentifier("splash", "drawable",
UnityPlayer.currentActivity.getPackageName());
bgView.setBackgroundResource(splash_bg);
bgView.setScaleType(ScaleType.CENTER);
mUnityPlayer.addView(bgView,r.getDisplayMetrics().widthPixels,
r.getDisplayMetrics().heightPixels);
} catch (Exception e) {
error("[onShowSplash]"+e.toString());
}
}
public void onHideSplash() {
try {
if(bgView == null)
return;
UnityPlayer.currentActivity.runOnUiThread(new Runnable() {
public void run() {
mUnityPlayer.removeView(bgView);
bgView = null;
}
});
} catch (Exception e) {
error("[onHideSplash]"+e.toString());
}
}
}