[Unity] Addressables 不使用異步讀取 (Resources.Load 改 Addressables)

[Unity] Addressables 不使用異步讀取 (Resources.Load 改 Addressables)


2022/07/11 12:30:08

把用 Resources.Load 的地方改 Addressables.LoadAssetAsync 時,遇到一些 init 跟 instance 綁定的問題。但又不想花一堆時間改架構,所以來找有沒有方法能夠同步讀取 addressables 的資源。以下筆記。

在使用 Unity Addressables 的時候,官方文件極力推薦我們使用非同步的方法來讀取資源,所有能查到的接口也大多以非同步的 Async 為名。的確,因為在寫 Addressables 程式的時候,我們無從得知這個包已經在本地還是需要從雲端下載下來,如果是後者的話,勢必會造成很長的讀取時間,這時如果我們使用同步寫法的話,整個程式就卡住動不了了。

但是,非同步程式的缺點之一就是有夠長,在 Unity 中 C# 原生的 task 又不太好用,還是要開 coroutine 來處理比較方便。如果我們能確保這個資源可以很快的讀進來,為何還要很麻煩的寫一大堆 async code?

原本非同步的程式可能會長這樣

Addressables.LoadAssetAsync<GameObject>("Something").Completed += result => {
GameObject g = result.Result;
//...
};

要用同步寫法就直接在 Load 後面加上 WaitForCompletion 就好了

GameObject g = Addressables.LoadAssetAsync<GameObject>("Something").WaitForCompletion();

:::error
Unity WebGL 無法使用!!!
:::

這樣我就只要把 Resources.Load("...")改成上面那樣就可以了,不用寫一堆 handler。而且 Addressables 有 InstantiateAsync,如果要直接 Instantiate 的場合又可以寫的更短,對於懶人如我更是一大福音 💯

// Resources.Load
Sprite s1 = Resources.Load<Sprite>("AAA");

// Addressables
Sprite s2 = Addressables.LoadAsync<Sprite>("AAA").WaitForCompletion();

// Addressables async
Addressables.LoadAsync<Sprite>("AAA").Completed += result => {
Sprite s3 = result.Result; // 在讀取完成之前都拿不到 s3
}


// Resources.Load
GameObject g1 = Instantiate(Resources.Load<GameObject>("AAA"));

// Addressables
GameObject g2 = Addressables.InstantiateAsync("AAA").WaitForCompletion();

// Addressables async
Addressables.InstantiateAsync("AAA").Completed += result => {
GameObject g3 = result.Result; // 在讀取完成之前都拿不到 g3
}