【Unity】Addressableアセットシステムでロード・アンロードする方法まとめ

UnityのAddressableアセットシステムでロード・アンロードする方法をまとめました。

Unity2019.2.10
Addressable1.3.8

はじめに

本記事ではAddressableアセットシステムを使ってロード・アンロードする方法をまとめます。
Addressableの概念や基礎知識についての説明はこの記事では省略しますが、
以下の記事にまとめていますので、必要に応じて参照してください。

light11.hatenadiary.com

基本的なロード方法と結果の待ち受け方

Addressableでは、Addressables.LoadAssetAsync()にアドレスを指定することでアセットをロードできます。

Addressables.LoadAssetAsync<GameObject>("Example");

このメソッドはAsyncOperationHandle構造体を返します。
結果を待ち受けるには、この構造体のCompletedでAsyncOperationHandle.Resultにアクセスします。

var handle = Addressables.LoadAssetAsync<GameObject>("Example");
handle.Completed += op => {
    if (op.Status == AsyncOperationStatus.Succeeded) {
        Instantiate(op.Result);
    }
};

AsyncOperationHandle構造体にはTaskも用意されているのでawaitで待ち受けることもできます。

var handle = Addressables.LoadAssetAsync<GameObject>("Example");
await handle.Task;
if (handle.Status == AsyncOperationStatus.Succeeded) {
    Instantiate(handle.Result);
}

また、下記のようにすればコルーチンで待ち受けることもできます。

var handle = Addressables.LoadAssetAsync<GameObject>("Example");
yield return handle;
if (handle.Status == AsyncOperationStatus.Succeeded) {
    Instantiate(handle.Result);
}

アセットをロードする

アセットをロードするには前節のようにAddressables.LoadAssetAsync()を使います。

Addressables.LoadAssetAsync<GameObject>("Example");

参照カウントを減らすにはAddressables.Release()にロードしたアセットか、AsyncOperationHandle構造体を渡します。

また、シリアライズしたAssetReferenceからロードする方法もあります。

using UnityEngine;
using UnityEngine.AddressableAssets;

public class Example : MonoBehaviour
{
    [SerializeField]
    private AssetReferenceGameObject _reference;

    private void Start()
    {
        _reference.LoadAssetAsync<GameObject>();
    }
}

この場合、Inspectorからアドレスを指定できます。

f:id:halya_11:20191113113349p:plain

AssetReferenceでロードした場合、リリースは次のように行います。

_reference.ReleaseAsset();

ちなみにサブアセットをすべて取得したい場合は以下のようにします。

Addressables.LoadAssetAsync<IList<Mesh>>("FbxExample");

特定のサブアセットを取得したい場合には以下のように中括弧をつかいます。

Addressables.LoadAssetAsync<Mesh>("FbxExample[skin]");

Sceneをロードする

シーンをロードするにはAddressables.LoadSceneAsync()を使います。

Addressables.LoadSceneAsync("ExampleScene");

Addressableを介さないシーン読み込みとは異なり、
Build Settingsにシーンを登録する必要はありません。

追加読み込みする場合には第二引数のLoadSceneModeをAdditiveにします。

Addressables.LoadSceneAsync("ExampleScene", UnityEngine.SceneManagement.LoadSceneMode.Additive);

シーンのアンロードをするにはAddressables.UnloadScene()を使います。
引数にはロード時のAsyncOperationHandleかSceneInstanceを渡します。

なお、LoadSceneMode.Singleでシーンを読み込んだ場合には古いシーンは自動的にアンロードされます。

GameObjectをロードしてInstantiateする

ここで、GameObjectをロードしてそのままInstantiateするようなケースを考えます。

var handle = Addressables.LoadAssetAsync<GameObject>("Example");
await handle.Task;
Instantiate(handle.Result);

このような場合、Addressables.InstantiateAsync()を使うとロードだけでなくインスタンス化まで行ってくれます。

var handle = Addressables.InstantiateAsync("Example");

この方法の特徴として、このメソッドで生成したGameObjectは所属するシーンが破棄されたタイミングでReleaseされます。
また、Addressables.ReleaseInstance()を使えば明示的にGameObjectの破棄と参照カウントのデクリメントをできます。
なおシーン切り替えでリリース済みのGameObjectに対してこれを呼んでもエラーにはなりませんでした。

ちなみにAssetReferenceGameObjectをつかってInstantiateすることもできます。

using UnityEngine;
using UnityEngine.AddressableAssets;

public class Example : MonoBehaviour
{
    [SerializeField]
    private AssetReferenceGameObject _reference;

    private void Start()
    {
        _reference.InstantiateAsync();
    }
}

関連

light11.hatenadiary.com

参考

docs.unity3d.com