【轉】Unity3d中製作Loading情境進度條所遇到的問題 LoadLevelAsync,AsyncOperation

來源:互聯網
上載者:User

標籤:產生   coroutine   res   卡頓   ogre   連續   記錄   img   沒有   

背景

通常遊戲的主情境包含的資源較多,這會導致載入情境的時間較長。為了避免這個問題,可以首先載入Loading情境,然後再通過Loading情境來載入主情境。因為Loading情境包含的資源較少,所以載入速度快。在載入主情境的時候一般會在Loading介面中顯示一個進度條來告知玩家當前載入的進度。在Unity中可以通過調用Application.LoadLevelAsync函數來非同步載入遊戲情境,通過查詢AsyncOperation.progress的值來得到情境載入的進度。

嘗試——遇到問題

第一步當載入完Loading情境後,調用如下的LoadGame函數開始載入遊戲情境,使用非同步載入的方式載入情境1(Loading情境為0,主情境為1),通過Unity提供的Coroutine機制,我們可以方便的在每一幀結束後調用SetLoadingPercentage函數來更新介面中顯示的進度條的數值。

public void LoadGame() {    StartCoroutine(StartLoading_1(1));}private IEnumerator StartLoading_1(int scene) {    AsyncOperation op = Application.LoadLevelAsync(scene);    while(!op.isDone) {                    SetLoadingPercentage(op.progress * 100);        yield return new WaitForEndOfFrame();    }        }

最後進度條的效果顯示如下:

進度條並沒有連續的顯示載入的進度,而是停頓一下切換一個數字,再停頓一下切換一個數子,最後在沒有顯示100%就情況下就切換到主情境了。究其原因在於Application.LoadLevelAsync並不是真正的後台載入,它在每一幀載入一些遊戲資源,並給出一個progress值,所以在載入的時候還是會造成遊戲卡頓,AsyncOperation.progress的值也不夠精確。當主情境載入完畢後Unity就自動切換情境,所以上述代碼中的while迴圈體內的代碼是不會被調用的,導致進度條不會顯示100%。

修補——100%完成

為了讓進度條能顯示100%,取巧一點的辦法是將AsyncOperation.progress的值乘上2,這樣當載入到50%的時候介面上就顯示100%了。缺點是當介面上顯示100%的時候,使用者還要等待一段時間才會進入遊戲。其實Unity提供了手動切換情境的方法,把AsyncOperation.allowSceneActivation設為false就可以禁止Unity載入完畢後自動切換情境,修改後的StartLoading_2代碼如下:

// this function is not workprivate IEnumerator StartLoading_2(int scene) {    AsyncOperation op = Application.LoadLevelAsync(scene);    op.allowSceneActivation = false;    while(!op.isDone) {        SetLoadingPercentage(op.progress * 100);        yield return new WaitForEndOfFrame();    }    op.allowSceneActivation = true;   }

我們首先將AsyncOperation.allowSceneActivation設為false,當載入完成後再設為true。代碼看上去沒有錯,但是執行的結果是進度條最後會一直停留在90%上,情境不會切換。通過列印log發現AsyncOperation.isDone一直為falseAsyncOperation.progress的值增加到0.9後就保持不變了,也就是說情境永遠不會被載入完畢。

在這個文章中找到了答案,原來把allowSceneActivation設定為false後,Unity就只會載入情境到90%,剩下的10%要等到allowSceneActivation設定為true後才載入,這不得不說是一個坑。所以代碼改為如下。當AsyncOperation.progress到達0.9後,就直接把進度條的數值更新為100%,然後設定AsyncOperation.allowSceneActivationture,讓Unity繼續載入未完成的情境。

private IEnumerator StartLoading_3(int scene) {    AsyncOperation op = Application.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;   }

最後的效果如下:

打磨——增加動畫

上述的進度條雖然解決了100%顯示的問題,但由於進度條的數值更新不是連續的,所以看上去不夠自然和美觀。為了看上去像是在連續載入,可以每一次更新進度條的時候插入過渡數值。這裡我採用的策略是當獲得AsyncOperation.progress的值後,不立即更新進度條的數值,而是每一幀在原有的數值上加1,這樣就會產生數字不停滾動的動畫效果了,迅雷中顯示下載進度就用了這個方法。

private IEnumerator StartLoading_4(int scene) {    int displayProgress = 0;    int toProgress = 0;    AsyncOperation op = Application.LoadLevelAsync(scene);    op.allowSceneActivation = 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;}

displayProgress用來記錄要顯示在進度條上的數值,最後進度條的動畫如下:

對比第一種的進度條

總結

如果在載入遊戲主情境之前還需要解析資料表格,產生對象池,進行網路連接等操作,那麼可以給這些操作賦予一個權值,利用這些權值就可以計算載入的進度了。如果你的情境載入速度非常快,那麼可以使用一個假的進度條,讓玩家看上幾秒鐘的loading動畫,然後再載入情境。總之進度條雖然小,但要做好也是不容易的。

 

 

https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.LoadSceneAsync.html

https://docs.unity3d.com/ScriptReference/AsyncOperation.html

AsyncOperation Description

Asynchronous operation coroutine.

You can yield until asynchronous operation continues, or manually check whether it‘s done (isDone) or progress (progress).

See Also: SceneManager.LoadSceneAsync, AssetBundle.LoadAsync.

Variables
allowSceneActivation Allow scenes to be activated as soon as it is ready.
isDone Has the operation finished? (Read Only)
priority Priority lets you tweak in which order async operation calls will be performed.
progress What‘s the operation‘s progress. (Read Only)
 

【轉】Unity3d中製作Loading情境進度條所遇到的問題 LoadLevelAsync,AsyncOperation

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.