Unity3d中製作Loading情境進度條所遇到的問題

來源:互聯網
上載者:User

背景

通常遊戲的主情境包含的資源較多,這會導致載入情境的時間較長。為了避免這個問題,可以首先載入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動畫,然後再載入情境。總之進度條雖然小,但要做好也是不容易的。

參考
  1. 阿高.Unity 顯示Loading(載入)進度 對於網上流行的方法進行更正
  2. Unity3d官方論壇.using allowSceneActivation

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.