关于Unity启动时间过长(启动黑屏时间长)的问题

发表于2017-10-30
评论0 3.9k浏览

Unity启动确实比其他引擎生成的游戏包慢些,关键是你启动的时候还要等上一段时间才显示Splash那个logo图,那么有什么办法可以解决启动时间过长(启动黑屏时间长)的这个问题呢?下面就通过一个具体的项目案例给大家做介绍。

最近项目有个蛋疼得需求,需要在启动界面加进度帧动画。。我也是醉了。

刚开始的思路:用Unity单独做个启动场景,让Splash那张图用成纯黑。那么问题来了,除了Unity刚启动的黑屏 显示Splash的黑图,再到显示loading动画界面至游戏场景加载出来,这时间都在十多秒以上了,。项目要求游戏从启动到显示游戏场景不能超过5秒。。哎。。太难为我了。好长一段时间都没能解决这个问题。

中间还想到一个方案就是用Android做一个插件的启动Activity场景,然后把这个场景设置成启动场景,之后再到Unity的场景。但是这个问题是无法绕过Unity的启动Splash。。无奈放弃。

因为不熟悉Android开发,所以。。。


我分析了Unity生成Android,对就是从Unity的UnityPlayerActivity入手。既然绕不过,那就不绕过,思路:

1、Unity生成的Android应用必然要从这个UnityPlayerActivity启动,那么他的启动Splash view必然显示在这个activity里面;

2、那么我可以继承UnityPlayerActivity,然后在onCreate方法里面在创建一个view来覆盖Splash,是的。这是可行的。激动。。。。。。

3、那这个启动界面上我们也同样可以做动画咯,O(∩_∩)O哈哈~现在的问题是当Unity Splash显示完毕之后,或者初始化完成之后怎么来隐藏我们所创建的View和动画。

4、现在我们要在Unity建一个空场景用来加载我们的第一个游戏场景,当加载完成之后通知我们的自定义Activity移除我们创建的界面和动画,是不是很完美呢?

现在不用看黑屏了,也绕过了Unity的Splash,只是加载的时间还是比其他引擎慢了,不过也能接受,因为很快的 就开到了我们的启动动画界面,等待加载到游戏场景。

最后贴点代码上来。。。。

package com.u3d.plugins;  
import java.util.Locale;  
import android.annotation.SuppressLint;  
import android.content.Context;  
import android.graphics.drawable.AnimationDrawable;  
import android.media.AudioManager;  
import android.media.AudioManager.OnAudioFocusChangeListener;  
import android.os.Bundle;  
import android.os.Handler;  
import android.os.Looper;  
import android.util.DisplayMetrics;  
import android.util.Log;  
import android.view.LayoutInflater;  
import android.view.View;  
import android.widget.ImageView;  
import com.unity3d.player.UnityPlayerActivity;  
public class MainActivity extends UnityPlayerActivity   
{  
    static final String TAG = "com.u3d.plugins";  
    private ImageView bgView = null;  
    private View view = null;  
    AnimationDrawable animationDrawable = null;  
    @SuppressLint("NewApi") @Override  
    protected void onCreate(Bundle arg0)   
    {  
        super.onCreate(arg0);  
        bgView=new ImageView(this);  
        String lanStr=Locale.getDefault().getLanguage();  
        String bgName="splash_bg_en";  
        if(lanStr.equals("zh"))  
        {  
            bgName="splash_bg_zh";  
        }  
        Log.d(TAG, "System Lan:" bgName);  
        int splash_bg=getResources().getIdentifier(bgName, "drawable", getPackageName());  
        bgView.setBackgroundResource(splash_bg);  
//      this.addContentView(bgView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));  
        mUnityPlayer.addView(bgView);  
        DisplayMetrics dm = new DisplayMetrics();  
        getWindowManager().getDefaultDisplay().getMetrics(dm);  
        float scaleX=dm.widthPixels/1024f;  
        float scaleY=dm.heightPixels/600f;  
        Log.d(TAG, "Screen Width:" dm.widthPixels ";Screen Height:" dm.heightPixels);  
        LayoutInflater flater = LayoutInflater.from(this);   
        int layoutID=getResources().getIdentifier("activity_splash", "layout", getPackageName());  
        view = flater.inflate(layoutID, null);  
        int frame_id=view.getResources().getIdentifier("splash_frame", "id", getPackageName());  
        ImageView frameView=(ImageView)view.findViewById(frame_id);//new ImageView(this);  
        frameView.setBackgroundResource(R.anim.splash_gif);  
//      this.addContentView(view, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));  
        mUnityPlayer.addView(view);  
        frameView.setScaleX(scaleX);  
        frameView.setScaleY(scaleY);  
//      frameView=new ImageView(this);  
//      frameView.setBackgroundResource(R.anim.splash_gif);  
//        
//      LinearLayout ll=new LinearLayout(this);  
//      LinearLayout.LayoutParams params=new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);  
//      params.leftMargin=scaleX*620;  
//      ll.setLayoutParams(params);  
//      ll.addView(frameView);  
//      mUnityPlayer.addView(ll);  
        animationDrawable = (AnimationDrawable) frameView.getBackground();  
        animationDrawable.start();  
    }  
    public void HideSplash()  
    {  
        Log.d(TAG, "HideSplash");  
        new Handler(Looper.getMainLooper()).post(new Runnable()  
        {  
            @Override  
            public void run()  
            {  
                Log.d(TAG, "HideSplash run");  
                animationDrawable.stop();  
                mUnityPlayer.removeView(bgView);  
                mUnityPlayer.removeView(view);  
//              ((ViewGroup)bgView.getParent()).removeView(bgView);  
//              ((ViewGroup)view.getParent()).removeView(view);  
                bgView=null;  
                view=null;  
                animationDrawable=null;  
            }  
        });  
    }  
    @Override  
    protected void onRestart() {  
        // TODO Auto-generated method stub  
        super.onRestart();  
        Log.d(TAG, "onRestart");  
        new Handler(Looper.getMainLooper()).post(new Runnable()  
        {  
            @Override  
            public void run()  
            {  
                muteAudioFocus(MainActivity.this,true);  
            }  
        });  
    }  
    @Override  
    protected void onResume() {  
        // TODO Auto-generated method stub  
        super.onResume();  
    }  
    @Override  
    protected void onPause()   
    {  
        // TODO Auto-generated method stub  
        super.onPause();  
    }  
    @Override  
    protected void onDestroy() {  
        // TODO Auto-generated method stub  
        super.onDestroy();  
    }  
    @Override  
    protected void onStop() {  
        // TODO Auto-generated method stub  
        super.onStop();  
        Log.d(TAG, "onStop");  
        new Handler(Looper.getMainLooper()).post(new Runnable()  
        {  
            @Override  
            public void run()  
            {  
                muteAudioFocus(MainActivity.this,false);  
            }  
        });  
    }  
    @Override  
    protected void onStart() {  
        // TODO Auto-generated method stub  
        super.onStart();  
        Log.d(TAG, "onStart");  
        new Handler(Looper.getMainLooper()).post(new Runnable()  
        {  
            @Override  
            public void run()  
            {  
                muteAudioFocus(MainActivity.this,true);  
            }  
        });  
    }  
    /**@param bMute 值为true时为关闭背景音乐。*/  
    public boolean muteAudioFocus(Context context, boolean bMute)   
    {  
        if(context == null)  
        {  
            Log.d(TAG, "context is null.");  
            return false;  
        }  
        boolean bool = false;  
        AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);  
        if(bMute)  
        {  
            int result = am.requestAudioFocus(afChangeListener,AudioManager.STREAM_MUSIC,AudioManager.AUDIOFOCUS_GAIN);  
            bool = result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;  
        }  
        else  
        {  
            int result = am.abandonAudioFocus(afChangeListener);  
            bool = result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED;  
        }  
        Log.d(TAG, "pauseMusic bMute=" bMute  " result=" bool);  
        return bool;  
    }  
    OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener()   
    {    
        public void onAudioFocusChange(int focusChange)   
        {    
            Log.d(TAG, "focusChange:" focusChange);  
            if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT)  
            {    
                // Pause playback     
            }  
            else if (focusChange == AudioManager.AUDIOFOCUS_LOSS)   
            {    
                muteAudioFocus(MainActivity.this,false);  
                // Stop playback     
            }   
            else if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK)  
            {    
                // Lower the volume     
            }   
            else if (focusChange == AudioManager.AUDIOFOCUS_GAIN)  
            {    
                // Resume playback or Raise it back to normal     
            }    
        }    
    };    
}  
Unity的启动场景代码:
using UnityEngine;  
using System.Collections;  
public class Launcher : MonoBehaviour  
{  
    public string loadScene;  
    void Awake()  
    {  
        Debug.Log("Launcher Awake");  
        DontDestroyOnLoad(gameObject);  
    }  
    void Start()  
    {  
        Debug.Log("Launcher Start");  
        StartCoroutine(LoadSence());  
    }  
    IEnumerator LoadSence()  
    {  
        if (!string.IsNullOrEmpty(loadScene))  
        {  
            Application.LoadLevelAsync(loadScene);  
        }  
        else  
        {  
            int levelCount = Application.levelCount;  
            int curLevel = Application.loadedLevel;  
            if (curLevel   1 < levelCount)  
                Application.LoadLevelAsync(curLevel   1);  
        }  
        yield return 0;  
        Invoke("OnFinish", 0.5f);  
        //OnFinish();  
    }  
    void OnFinish()  
    {  
        if (Application.platform.Equals(RuntimePlatform.Android))  
        {  
            using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))  
            {  
                using (AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"))  
                {  
                    jo.Call("HideSplash");  
                }  
            }  
        }  
        Destroy(gameObject);  
    }  
}  
最后把我们的Android项目生成jar包供Unity使用

anim文件夹放了动画得的配置文件,layout布局文件。

<?xml version="1.0" encoding="utf-8"?>  
<manifest  
    xmlns:android="http://schemas.android.com/apk/res/android"  
    package="com.unity3d.player"  
    android:installLocation="preferExternal"  
    android:versionCode="1"  
    android:versionName="1.0">  
    <supports-screens  
        android:smallScreens="true"  
        android:normalScreens="true"  
        android:largeScreens="true"  
        android:xlargeScreens="true"  
        android:anyDensity="true"/>  
    <application  
        android:theme="@android:style/Theme.NoTitleBar.Fullscreen"  
        android:icon="@drawable/launcher_icon"  
        android:label="@string/app_name"  
        android:debuggable="true">  
        <activity android:name="com.u3d.plugins.MainActivity"  
                  android:label="@string/app_name">  
            <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" />  
        </activity>  
    </application>  
</manifest> 

<?xml version="1.0" encoding="utf-8"?>  
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:id="@ id/splash_bg"  
    android:layout_width="fill_parent"  
    android:layout_height="fill_parent"  
    android:orientation="horizontal" >  
    <LinearLayout  
        android:layout_width="wrap_content"  
        android:layout_height="match_parent"  
        android:layout_weight="6.3"  
        android:orientation="horizontal" />  
  <LinearLayout  
        android:layout_width="wrap_content"  
        android:layout_height="match_parent"  
                android:layout_weight="3.7"  
        android:orientation="vertical" >  
    <LinearLayout  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_weight="7.86"  
        android:orientation="horizontal" />  
        <LinearLayout  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_weight="2.14"  
        android:orientation="horizontal" >  
                <ImageView  
        android:id="@ id/splash_frame"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"/>  
            </LinearLayout>  
    </LinearLayout>  
</LinearLayout>  

<?xml version="1.0" encoding="UTF-8"?>  
<animation-list android:oneshot="false"  
  xmlns:android="http://schemas.android.com/apk/res/android">  
    <item android:duration="300" android:drawable="@drawable/loading_1" />  
    <item android:duration="300" android:drawable="@drawable/loading_2" />  
    <item android:duration="300" android:drawable="@drawable/loading_3" />  
</animation-list>  
是不是发现现在自己的Unity启动时间变短了些呢。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论