1. 程式人生 > >【Unity3d】淺談非同步載入場景

【Unity3d】淺談非同步載入場景

大家好,我是sakai,這是我的第一篇分享心得部落格,以後我會陸續總結自己學習U3D的經驗,希望能和大家一起交流共同進步。  

我們玩很多遊戲,在載入切換場景的時候往往需要載入很多的資源,因此需要載入比較長的時間,為了有更好的玩家互動,讓玩家可以在等待載入的同時也不會覺得無聊,就需要一個好的緩衝過程了。這時候我們用到的就是非同步載入。在載入的時候我們可以通過各種各樣的方式給玩家一種“假象”,讓玩家可以知道遊戲的載入進度。很多rpg遊戲用的是滑動器+tips標籤頁來顯示,今天我就給大家介紹一下我的使用心得,廢話不多說,下面貼程式碼。

<pre name="code" class="csharp">using System;
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using Random = UnityEngine.Random;


public class Loading : MonoBehaviour {


    //非同步物件  
    private AsyncOperation _asyncOperation;
    //顯示tips的文字
    private Text _tip;
    //tips的集合
    private string[] _tips = new string[]
    {
        "阪井泉水",
        "上野樹里",
        "長澤雅美",
        "戶田惠梨香"
    };
    //更新tips的時間間隔
    private const float _updateTime = 1f;
    //上次更新的時間
    private float _lastUpdateTime = 0;
    //滑動條
    private Slider _slider;
    //顯示進度的文字
    private Text _progress;
	// Use this for initialization
	void Start ()
	{
	    _tip = GameObject.Find("Text").GetComponent<Text>();
	    _slider = GameObject.Find("Slider").GetComponent<Slider>();
	    _progress = GameObject.Find("Progress").GetComponent<Text>();
            SetTip();
	    StartCoroutine(LoadAsync("NextScene"));
	}
	
	// Update is called once per frame
	void Update ()
    {
        //首先判斷是否為空,其次判斷是否載入完畢
        if (_asyncOperation != null && !_asyncOperation.allowSceneActivation)
        {
            //開始更新tips
            if (Time.time - _lastUpdateTime >= _updateTime)
            {
                _lastUpdateTime = Time.time;
                SetTip();
            }
        }
	}
    /// <summary>
    /// 設定載入標籤
    /// </summary>
    private void SetTip()
    {
        int temp = Random.Range(0, _tips.Length);
        _tip.text = _tips[temp];
    }
    /// <summary>
    /// 攜程進行非同步載入場景
    /// </summary>
    /// <param name="sceneName">需要載入的場景名</param>
    /// <returns></returns>
    IEnumerator LoadAsync(string sceneName)
    {
        //當前進度
        int currentProgress = 0;
        //目標進度
        int targetProgress = 0;
       _asyncOperation = Application.LoadLevelAsync(sceneName);
        //unity 載入90%
        _asyncOperation.allowSceneActivation = false;
        while (_asyncOperation.progress<0.9f)
        {
            targetProgress = (int) _asyncOperation.progress*100;
            //平滑過渡
            while (currentProgress<targetProgress)
            {
                ++currentProgress;
                _progress.text= String.Format("{0}{1}",currentProgress.ToString(),"%");
                _slider.value = (float) currentProgress/100;
                yield return new WaitForEndOfFrame();
            }
        }
        //自行載入剩餘的10%
        targetProgress = 100;
        while (currentProgress < targetProgress)
        {
            ++currentProgress;
            _progress.text = String.Format("{0}{1}", currentProgress.ToString(), "%");
            _slider.value = (float)currentProgress / 100;
            yield return new WaitForEndOfFrame();
        }
        _asyncOperation.allowSceneActivation = true;
    }
}



本文的核心部分在於第二個攜程LoadAsync部分,我使用的是Unity自帶的方法Application.LoadLevelAsync,由於progress在載入到0.9的時候會停止載入,所以在0.9-1的過渡需要我們自己手動執行。在這裡還需要提一下的就是,我使用了allowSceneActivation這個標誌位來區分是否非同步載入完畢(false的時候可以控制非同步載入的場景暫時不進入)。

好了,下面讓我們來看一下執行的效果




今天的分享就到此結束了,歡迎大家一起來探討,本人的程式碼規範寫的很爛,有更好的寫法歡迎指出。