AssetBundle異步加載被中斷的問題


在使用異步接口 yield return AssetBundle.ASyncLoad的時候,難免會想到:這個異步處理完之前如何Cancel掉這個任務?
也就是一個AssetBundle加載到一半,現在要放棄加載,應該怎么處理?

評論 分享
10條回復

無法CANCEL

評論 分享

Unity的接口里沒有中斷操作,但是可以在自己項目的ABMgr模塊給業務邏輯層提供一個可中斷的接口。也就是Mgr里加載好資源后,如果業務層不需要了,則不返回/不執行回調。至於這個“不需要”的資源是要緩存,還是卸載就得根據自己項目來了。

評論 分享

分享一個小的Unity文檔上的坑吧,其實我也不知道答案,可能希望有源碼的朋友幫忙看看。
在異步請求一個AssetBundle的時候,會返回一個AssetBundleCreateRequest對象,Unity的官方文檔上寫AssetBundleCreateRequest.assetBundle的時候這樣說:

Description
Asset object being loaded (Read Only).

Note that accessing asset before isDone is true will stall the loading process.

用了Stall這樣一個詞,我們之前理解Stall是停止的意思,以為這個接口的調用可以將異步請求打斷,所以借助這個特性應用在“同一個AssetBundle正在被異步加載的過程中來了一個同步請求”這樣的情況下。
今天看到這個問題,又讀了讀這個文檔,感覺Stall這個詞並不是停止的意思,而更可能是“拖延”的意思。如果是一個異步加載請求,那么是在另外的線程里執行的,這時候如果有主線程的訪問請求的話,應該會有跨線程的加鎖邏輯,從而可能導致加載變得更慢。如果是停止的話,我覺得文檔應該使用Stop這樣更加明確的單詞……

當然這個是我個人的猜測,並不一定真的是這樣。。。如果有其他朋友知道准確的意思也煩請告知~

評論 2 分享
  • K
    kent

    會有一個資源鎖,體現在Loading.LickPersistentManager,這時要控制依賴關系及同一時刻提取asset的數量。

  •  
    賈偉昊 回復kent

    感謝回復~

 
S

碰到的問題和我一樣呢, 最后我們是使用promise方式封裝了資源加載的接口。
返回的handle對象狀態一旦凝固就不會再改變.

////code1
op = loadasset()
yield return op
if op.error != nil then
  log("fail=" + op.error)
end

////code2
op:reject("next scene is loading")
評論 分享

image.png

看到賈偉昊說到的這個問題,很激動地去看了一下API和UnityReferenceSource。由於項目一直在用5.6版本,2017和2018的AB這塊還沒測試過。5.6是肯定不能取消或者block獲取到AB資源的,看新的Doc里面都提到了能block獲取到資源,referenceSource中AB的API也提到了,asset的API中沒有提到。理解應該是在異步沒有完成之前,訪問資源可以變成同步馬上獲取到該資源,有測試過的同學可以回答一下。如果真是這樣,那就太好了,相信很多項目的設計上都是同步與異步並存的,只是繞過了同步加載一個正在異步加載資源的問題。Unity如果這塊修改了,就可以完美解決同步加載一個正在異步加載資源的問題了。

鑒於Unity Doc被坑過幾次,更相信ReferenceSource里的,猜測AB也許實現了同步訪問正在異步加載的資源,asset沒有實現。

評論 2 分享
  •  
    灰灰

    2017也是,異步沒完成前直接訪問asset會同步完成加載

  • L
    leeman 回復灰灰

    有具體例子可以看一下怎么實現嗎?現在也再糾結這個東西

 
C

我們之前的項目,無論是同步加載還是異步加載,都是以異步的方式寫代碼,就是為了解決這種不確定性

評論 分享

沒法取消異步加載操作,但是通過在isDone之前直接訪問Asset可以同步加載完成資源,也算中止異步加載操作吧。

評論 分享
C

先異步加載1.ab,異步未完成時,直接同步加載該1.ab。
此時會有類似的error:The asset bundle ‘’ can’t be loaded because another asset bundle with the same files are already loaded。直接忽略該錯誤即可。

評論 2 分享
  • L
    leeman

    直接忽略?難道是已經加載成功了?報錯不准?

  • C
    cloud

    官方說是保護性的提示,無任何副作用。

 
L

同一幀相同資源先調異步再調同步辦法
上面說的比較原理。我來直接上代碼吧。造福大家
abrequest = AssetBundle.LoadFromFileAsync(path)
abrequest .assetBundle.Unload(false)
ab = AssetBundle.LoadFromFile(path)
這樣會直接同步回來ab,但是會破壞原來異步的回調值 里面abreast.assetbundle 會變空不太好。
還有一種辦法是最后一句改為
asset a =abrequest.assetBundle.asset
這樣原來異步的回調可以正常執行,同步也可以直接返回值。是一個比較好的解決方案。原來代碼的邏輯改動小。

評論 2 分享
  • 贊一個,方案可行

  • X
    xp

    沒看懂

 
Z

在Unity2018.1.1f上測試了,可以通過獲取bundle的操作來打斷異步操作,使其改為同步加載。具體示例代碼:

        AssetBundleCreateRequest abRequest = AssetBundle.LoadFromFileAsync(path);
	abRequest.assetBundle.Unload(true);
        AssetBundle ab = abRequest.assetBundle;
        if (ab == null)
        {
            ab = AssetBundle.LoadFromFile(path);
            var assets = ab.LoadAllAssets();
            foreach (var item in assets)
            {
                Debug.Log(item.name);
            }
        }
        else
        {
            var assets = ab.LoadAllAssets();
            foreach(var item in assets)
            {
                Debug.Log(item.name);
            }
        }

如果執行Unload(true), 那么這一行代碼的本質是將異步改為同步,然后加載該bundle,再釋放該bundle,下面會執行LoadFromFile操作。如果注釋掉該執行代碼,則直接獲取assetbundle的操作返回的是同步加載的bundle,會執行else語句塊中的代碼。
大家可以測試一下,我測試沒有問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM