ResourceLocatorを実装して独自のキーでリソースを読み込む方法についてまとめました。
Unity2020.3.17f1
Addressables 1.18.16
ResourceLocator?
AddressableアセットシステムにはIResourceLocatorというインターフェースが存在します。
これには以下のようなLocateメソッドが定義されていて、与えられたキーに対してそのリソースの場所(リソースロケーション)を返します。
// locationsにリソースロケーションが入る // 戻り値は成功したらtrue bool Locate(object key, Type type, out IList<IResourceLocation> locations);
デフォルトではこのインターフェースを実装したResourceLocationMapなどのクラスが存在します。
このクラスで、コンテンツカタログから得た情報を使ってキーに対応するリソースロケーションを返しています。
さてこのResourceLocatorは内部的に複数個登録されています。
あるキーに対して、リソースロケーションが正常に得られる(上述のLocateメソッドがtrueを返す)ResourceLocatorの結果が使われます。
// 全てのResourceLocatorを取得
Addressables.ResourceLocators;
さらにユーザがResourceLocatorを追加、削除できるAPIも公開されています。
// 追加、削除
Addressables.AddResourceLocator(resourceLocator);
Addressables.RemoveResourceLocator(resourceLocator);
Addressables.ClearResourceLocators();
ここまでの情報をまとめると、アドレスではなく自身で定義した独自のキーでリソースを読み込むということも可能なはずです。
そこで次節では、ResourceLocatorを実装して独自のキーでリソースを読み込んでみます。
GUIDをキーにしてAssetDatabaseからリソースを読み込むResourceLocatorを作る
今回は簡単なテストのために、GUIDを渡すとAssetDatabase経由でそのGUIDを持つリソースを読み込んでくれるResourceLocatorを作ってみます。
まずソースコードは以下の通りです。
#if UNITY_EDITOR using System; using System.Collections.Generic; using UnityEditor; using UnityEngine.AddressableAssets.ResourceLocators; using UnityEngine.ResourceManagement.ResourceLocations; using UnityEngine.ResourceManagement.ResourceProviders; using Object = UnityEngine.Object; namespace ResourceLocatorTest { public class GuidResourcesLocator : IResourceLocator { public bool Locate(object key, Type type, out IList<IResourceLocation> locations) { var guid = key as string; if (guid == null) { locations = null; return false; } // GUIDからアセットパスを取得 var assetPath = AssetDatabase.GUIDToAssetPath(guid); if (string.IsNullOrEmpty(assetPath)) { locations = null; return false; } locations = new List<IResourceLocation>(); // アセットパスをAssetDatabaseProviderにIDとして渡して、UnityEngine.Objectを読み込む locations.Add(new ResourceLocationBase(guid, assetPath, typeof(AssetDatabaseProvider).FullName, typeof(Object))); return true; } public IEnumerable<object> Keys => null; public string LocatorId => nameof(GuidResourcesLocator); } } #endif
Locateメソッド内で、キーが有効なGUIDだった場合にResourceLocationBaseを生成して返しています。
リソースロケーションの指定方法は上記のように、ResourceProviderの型を表す文字列とそれに渡すIDをセットにして生成します。
今回はAddressableのAssetDatabaseProviderを使い、GUIDから取得したアセットパスをIDとして渡しています。
動作確認
それでは次に前節で作ったGuidResourcesLocatorの動作確認をしていきます。
以下のように、GUIDを指定してGameObjectを読み込むスクリプトを記述します。
using System.Linq; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.ResourceManagement.ResourceProviders; namespace ResourceLocatorTest { public class Example : MonoBehaviour { [SerializeField] private string _guid; private async void Start() { #if UNITY_EDITOR // 前節で作ったGuidResourcesLocatorを登録 Addressables.AddResourceLocator(new GuidResourcesLocator()); // AssetDatabaseProviderを使用するので、ResourceManagerに登録 var resourceProviders = Addressables.ResourceManager.ResourceProviders; if (resourceProviders.All(x => x.GetType() != typeof(AssetDatabaseProvider))) { resourceProviders.Add(new AssetDatabaseProvider()); } #endif // GUIDをキーにして読み込む var handle = Addressables.LoadAssetAsync<GameObject>(_guid); await handle.Task; if (handle.Status == AsyncOperationStatus.Succeeded) { Instantiate(handle.Result); } Debug.Log(handle.Status); } } }
説明はコメントに書いた通りです。
使用するResourceProviderは事前にResourceManagerに登録しておく必要があるので、
GuidResourcesLocatorで使用しているAssetDatabaseProviderの登録を忘れないようにしてください。
GUIDを指定してPrefabを読み込むと正常にインスタンス化されることを確認できます。