1. 程式人生 > >Unity AssetBundle載入 Update與協程的取捨

Unity AssetBundle載入 Update與協程的取捨

    同步載入沒有爭議,api的呼叫非常簡單。這裡主要記錄在構建AssetBundleManager時,非同步載入資源請求採用哪種方案進行回撥。

    IEnumerator Start()
    {
        var bundleLoadRequest = AssetBundle.LoadFromFileAsync(Path.Combine(Application.streamingAssetsPath, "myassetBundle"));
        yield return bundleLoadRequest;

        var myLoadedAssetBundle = bundleLoadRequest.assetBundle;
        if (myLoadedAssetBundle == null)
        {
            
Debug.Log
("Failed to load AssetBundle!"); yield break; } var assetLoadRequest = myLoadedAssetBundle.LoadAssetAsync<GameObject>("MyObject"); yield return assetLoadRequest; GameObject prefab = assetLoadRequest.asset as GameObject; Instantiate(prefab); myLoadedAssetBundle.Unload(false); }

    可能正是這種示例,導致大部分人在學習過程中,優先採用了開啟協程,使用yield return的方式來等待www或者asyncOperation執行結束,也導致網上很多案例全是仿照這個模式來寫的,搞得半路出家的程式(愚蠢的我)一直理解為,在非同步載入資源的時候,需要呼叫yield retur (MoveNext)進行驅動,才能保證資源載入的完成,直到今天學習了一下官方的AssetBundleManager(https://docs.unity3d.com/Manual/AssetBundles-Manager.html),故記錄下幾個誤區,與自己對ABManager載入方案選型的思考。

    1. WWW、ab. LoadAssetAsync  、AssetBundle.LoadFormFileAsync 一旦呼叫api進行請求申請後,不需要使用yield return進行驅動。使用yield return 的目的,只是檢查當前返回的非同步物件是否能夠MoveNext,而Unity對這些物件的MoveNext方法封裝大體上就是返回了一個 !isDone,即當isDonw == true 的時候,yield return 會結束並繼續往下進行程式碼。

    2.非同步載入申請發起後,快取返回的物件,在Update中等週期性函式內呼叫 operation.isDone,如果為true在取資源,和把取資源的操作放在yield return 下一個效果。

    3.非同步載入資源是主執行緒操作。AsyncOperation能夠設定優先順序,說明Unity自身也有對這些請求的快取,然後遍歷驅動。

    4.資源載入時,邏輯程式碼新開的協程,在載入完成後會產生少量GC,Update等週期性函式詢問isDone時會一直執行,即使在沒有資源載入時,會多走一句判斷,產生少量冗餘。

   5.個人比較偏向update輪詢的方式,因為在大量資源同時載入的過程中,本就是容易產生效能瓶頸的點,這時候每個資源又多開闢了一個協程,擔心這點GC與記憶體佔用,會影響使用者體驗。

    6.AsyncOperation有回撥completed,會在isDone時自動呼叫(但在5.6上沒有找到),如果18.2Unity提供isDone的回撥,那麼upDate輪詢都沒必要了,直接使用AssetBundle內部構建的協程進行驅動的同時,可以將載入完成的bundle進行快取與管理。

    7.最後個人覺得無論任何時候,無腦使用協程進行資源載入都是一個比較愚蠢的方案,搭配Update(可在密集載入資源時開啟輪詢,場景初始化預載入時),或者直接使用Update(每幀多一句if operationsCount> 0)。第二種方案還可以將update內的輪詢方法繫結在Game的Update中,這樣連繼承MonoBehaviour類的開銷都省了。

以上觀點僅代表個人看法,如有錯誤歡迎指正,發現問題會第一時間更改,以免誤導比我還新的新人。