背景
通常游戲的主場景包含的資源較多,這會導致加載場景的時間較長。為了避免這個問題,可以首先加載Loading場景,然后再通過Loading場景來加載主場景。由於Loading場景包含的資源較少,所以加載速度快。在加載主場景時一般會在Loading界面中顯示一個進度條來告知玩家當前加載的進度。在Unity中可以通過調用SceneManager.LoadLevelAsync來異步加載游戲場景,通過查詢AsyncOperation.progress來得到場景加載的進度。
而SceneManager.LoadLevelAsync並不是真正的后台加載,它在每一幀加載一些游戲資源,並給出一個progress值,所以加載的時候會造成游戲卡頓,AsyncOperation.progress的值也不夠精確。當主場景加載完畢后Unity就自動切換場景,這可能會導致進度條不會顯示100%。
進度條顯示100%
Unity提供了手動切換場景的方法,把AsyncOperation.allowSceneActivation設置為false,就可以禁止Unity加載完畢后自動切換場景。但是這種方法的執行結果是進度條最后會一直停留在90&上,場景就不會切換,此時打印AsyncOperation.isDone一直是false,剩下的10%要等到AsyncOperation.allowSceneActivation設置為true后才加載完畢。
所以當加載到90%后需要手動設置數值更新為100%,讓Unity繼續加載未完成的場景。
private IEnumerator StartLoading_1 (int scene){ AsyncOperation op = SceneManager.LoadLevelAsync(Scene); op.allowSceneActivation = false; while(op.progress <= 0.9f){ SetLoadingPercentage(op.progress * 100); yield return new WaitForEndOfFrame(); } SetLoadingPercentage(100); yield return new WaitForEndOfFrame(); op.allowSceneActivation = true; } public void LoadGame(){ StartCoroutine(StartLoading_1(1)); }
平滑顯示進度條
上述的進度條雖然解決了100%顯示的問題,但由於進度條的數值更新不是連續的,所以看上去不夠自然和美觀。為了看上去像是在連續加載,可以每一次更新進度條的時候插入過度數值。比如:獲得AsyncOperation.progress的值后,不立即更新進度條的數值,而是每一幀在原有的數值上加1,這樣就會產生數字不停滾動的動畫效果了。
private IEnumerator StartLoading_2(int scene){ int displayProgress = 0; int toProgress = 0; AsyncOperation op = SceneManager.LoadLevelAsync(scene); op.allowSecneActivation = false; while(op.progress < 0.9f){ toProgress = (int)op.progress * 100; while(displayProgress < toProgress){ ++displayProgress; SetLoadingPercentage(displayProgress); yield return new WaitForEndOfFrame(); } } toProgress = 100; while(displayProgress < toProgress){ ++displayProgress; SetLoadingPercentage(displayProgress); yield return new WaitForEndOfFrame(); } op.allowSceneActivation = true; }
總結:
如果在加載游戲場景之前還需要解析數據表格,生成對象池,進行網絡連接等操作,那么可以給這些操作賦予一個權值,利用這些權值就可以計算加載的進度了。如果你的場景加載速度非常快,那么可以使用一個假的進度條,讓玩家看幾秒鍾loading動畫,然后再加載場景。
