你好,我是跟着大智學Unity的萌新,我叫小新,這是我本週的學習總結報告哦。
大智:“小新,這周學習有沒有遇到什麼問題呢?”
小新:“確實遇到了,那個Addressables.LoadAssetsAsync
API,我有一次怎麼都加載不出來資源,倒騰了半天,最後發現是參數傳的不對。。。”
大智:“那你現在搞明白了沒?”
小新:“基本搞明白了。。。”
大智:“那你把Addressable中的加載API總結一下吧~我看看你到底搞明白了沒。”
小新:“好嘞。”
Addressable系統的加載資源API
Addressable中加載資源主要有兩個途徑:
- 通過AssetReference加載
- 使用Addressables類中的靜態方法通過地址/Label加載
1.AssetReference加載的API
使用AssetReference
類訪問Addressable資產時無需知道他們的地址字符串,但是需要在Inspector上關聯。使用流程如下:
- 新建一個腳本,任何可序列化的組件都支持
AssetReference
變量(例如,繼承MonoBehaviour的腳本,ScriptableObject或其他可序列化的類)。 - 在組件中添加一個
AssetReference
類型的公共變量(例如public AssetReference explosion;
)。 - 在Inspector中,將資產從“ Project”窗口拖到
AssetReference
字段上(非Addressable資產也可以拖,會自動標記爲Addressable),或從項目中已經設置的可尋址資產的下拉列表中進行選擇(如下所示)。
要加載或實例化AssetReference
資產,需要調用其相應的方法。例如:
僅加載到內存中,多用於貼圖、材質、動畫、音頻等資產:
[AssetReference的變量名].LoadAssetAsync<GameObject>();
直接實例化到場景中,一般用於Prefab:
[AssetReference的變量名].InstantiateAsync(pos, rot);
加載場景:
[AssetReference的變量名].LoadSceneAsync();
注:這幾個API都是異步操作,異步操作詳解在大智的教程中有(洪流學堂公衆號中回覆addr
可以獲取),在這就不多說了。
2. 使用Addressables類中的靜態方法通過地址/Label加載
Addressables類中有加載單個資源的API和多個資源的API。
加載單個資源
在腳本中使用字符串地址加載資產,先聲明using UnityEngine.AddressableAssets;
名稱空間,然後調用以下方法:
僅加載到內存中,多用於貼圖、材質、動畫、音頻等資產:
Addressables.LoadAssetAsync<GameObject>("AssetAddress");
加載完成後並不會將所需的資產實例化到場景中。要將資產添加到場景中,還需要一步:實例化。
還有一個加載和實例化二合一的接口,這個接口會加載資產,然後立即將其實例化到場景中:
Addressables.InstantiateAsync("AssetAddress");
這會將指定地址的資產實例化到場景中。
注意:上面的API是異步操作。你可以在資產完成加載後提供一個回調來使用資產,異步操作詳解在大智的教程中有(洪流學堂公衆號中回覆addr
可以獲取),在這就不多說了。
using System.Collections;
using System.Collections.Generic;
using UnityEngine.AddressableAssets;
using UnityEngine;
public class AddressablesExample : MonoBehaviour {
GameObject myGameObject;
void Start{
Addressables.LoadAssetAsync<GameObject>("AssetAddress").Completed += OnLoadDone;
}
private void OnLoadDone(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle<GameObject> obj)
{
// In a production environment, you should add exception handling to catch scenarios such as a null result.
myGameObject = obj.Result;
}
}
一次加載多個資產
一次加載多個資產通常是使用Label加載。
如上圖所示的分組策略,可以按如下方式加載HD的皮膚貼圖。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class TextureController : MonoBehaviour
{
public Renderer m_ReferencedMaterial;
public void SwitchToHighDef()
{
LoadTexture("ArcherColor", "HD");
}
void LoadTexture(string key, string label)
{
Addressables.LoadAssetsAsync<Texture2D>(new List<object> { key, label }, null, Addressables.MergeMode.Intersection).Completed
+= TextureLoaded;
}
void TextureLoaded(AsyncOperationHandle<IList<Texture2D>> obj)
{
m_ReferencedMaterial.material.mainTexture = obj.Result[0];
}
}
在這一定要注意:LoadAssetsAsync有三個重載:
public static AsyncOperationHandle<IList<TObject>> LoadAssetsAsync<TObject>(object key, Action<TObject> callback);
public static AsyncOperationHandle<IList<TObject>> LoadAssetsAsync<TObject>(IList<object> keys, Action<TObject> callback, MergeMode mode);
public static AsyncOperationHandle<IList<TObject>> LoadAssetsAsync<TObject>(IList<IResourceLocation> locations, Action<TObject> callback);
通常我們使用前兩種重載:
第一種:用於加載單個標籤或地址。
第二種:用於加載地址+標籤的形式。用第二種時一定要注意加上第三個參數MergeMode。否則重載匹配時就會去匹配第一個重載,會導致找不到資源。
MergeMode是什麼呢?翻譯過來是合併模式。
public enum MergeMode
{
None = 0,
UseFirst = 0,
Union,
Intersection
}
採用第二種重載加載時,其實會去先查詢每一個地址/標籤對應的資源,然後再根據MergeMode進行最終結果的計算。
舉個栗子:
比如傳入的參數是new List<object>{"cube", "red"}
,根據cube查詢出來的資源有A、B、D,根據red查詢出來的資源有C、D、E。
那麼MergeMode是Node或UseFirst時,會取第一個key查詢到的資源:A、B、D;
MergeMode是Union時,會取所有key查詢到的資源的並集:A、B、C、D、E;
MergeMode是Intersection時,會取所有key查詢到的資源的交集:D。
總結
大智:“看來這個LoadAssetsAsync
就是你栽了的API吧?”
小新:“沒錯。”
大智:“之前我都有講過哦,一定要注意這些細節。特別是方法有重載的時候,要注意查閱API文檔或者閱讀源碼,不能想當然。”
《大話Unity2019》,大智帶小新學Unity2019的有趣經歷,讓你學Unity更簡單。