Help us understand the problem. What is going on with this article?

めんどくささから解放!AddressableAssetSystemの最新情報と使える小技!

初めに

AddressableAssetSystemは皆さん使われていますか?使っていても使っていなくても、ものすごく便利な機能だと思うので使っていない人はぜひ導入を検討してみてください!
ここではAddressableAssetSystemについての最近使えるようになった機能についての解説と個人的に便利だと思う小技について解説を行っていきます。またコード自体はパブリックドメインとしておきますのでご自由にお使いください。

機能の名前が変更になった(1.3.2以降)

以前の機能の名称から少し変更になりました。以下にその表を記載しておくので参考にしてください

1.3.3以前 1.3.3以降
PlayMode
Fast Mode Use Asset Database
Virtual Mode Simulate Groups
Packed Mode Use Existing Build
BundledAssetGroupSchema Content Packing & Loading
ContentUpdateGroupSchema Content Update Restriction
Prepare for Content Update Tools/Check for Content Update Restriction
Build for Content Update Update a Previous Build
Profiler Event Viewer

Addressables.PreloadDependenciesの名前の変更(0.6.6以降)

古いバージョンのAddressables.PreloadDependenciesはAddressables.DownloadDependenciesに変わりました。

SpriteAtlasなどから個別にSpriteなどをAssetReferenceとして取り出せるようになった!(1.2.2以降)

この機能がどのように便利かというと、従来はSpriteAtlasからSpriteを取り出したいとき、GetSpriteで取り出すほかうまく動作させることが出来ませんでしたがこの機能があればAssetRefrenceにSpriteAtlasを指定するとサブアセットを取り出せるようになります。
いままで

LoadImage.cs
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.U2D;

public class LoadImage : MonoBehaviour
{
    [SerializeField] AssetReference target;
    private void Start()
    {
        Addressables.LoadAssetAsync<SpriteAtlas>(target).Completed += Loaded;
    }

    private void Loaded(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle<SpriteAtlas> handle)
    {
        var atlas = handle.Result;
        var sprite = atlas.GetSprite("利用したいイメージ");
    }
}

と表記を行って、targetにはSpriteAtlasを入れてロードを行っていましたがこの新しい機能を使うとコード自体は単純な

LoadImage.cs
using UnityEngine;
using UnityEngine.AddressableAssets;

public class LoadImage : MonoBehaviour
{
    [SerializeField] AssetReference target;
    private void Start()
    {
        Addressables.LoadAssetAsync<Sprite>(target).Completed += Loaded;
    }

    private void Loaded(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle<Sprite> handle)
    {
        var sprite = handle.Result;
    }
}

Spriteを読み込むScriptでよくなり
image.png
SpriteAltasを指定するとEditorの画面でSpriteAltasに内包されているアセットを参照することが可能なため文字列での参照を行わずにSpriteを取得することができます。

UnityCloludBuildでビルドできるようになった

そのままです
image.png
CloudBuildのConfig欄にAddressableの欄が追加されここだけで完結することが可能となりました。
コンテンツだけをビルドするモードもあるので

Taskでawaitできるようになった

文字通りですAsyncOperationHandleがTaskを持つようになったので

ImageTaskLoad.cs
using UnityEngine;
using UnityEngine.AddressableAssets;

public class ImageTaskLoad: MonoBehaviour
{
    [SerializeField] AssetReference target;
    async void Start()
    {
        Sprite image = await Addressables.LoadAssetAsync<Sprite>(target).Task;
    }
}

というUnityっぽくないモダンなコードを書くことが出来るようになりました。
またもしUniTaskを使っている場合は

ImageTaskLoad.cs
using System;
using System.Threading;
using UniRx.Async;
using UnityEngine.ResourceManagement;
using UnityEngine.ResourceManagement.AsyncOperations;

public static class AddressableGetAwaiterExtention
{
    public static UniTask<T>.Awaiter GetAwaiter<T>(this AsyncOperationHandle<T> asset)
    {
        UniTaskCompletionSource<T> completionSource = new UniTaskCompletionSource<T>();
        asset.Completed += (result) =>
        {
            switch (result.Status)
            {
                case AsyncOperationStatus.None:
                    break;
                case AsyncOperationStatus.Succeeded:
                    completionSource.TrySetResult(result.Result);
                    break;
                case AsyncOperationStatus.Failed:
                    completionSource.TrySetException(result.OperationException);
                    break;
                default:
                    throw new ArgumentOutOfRangeException(result.OperationException.ToString());
            }
           // completionSource.TrySetResult(result.Result);
        };
        return completionSource.Task.GetAwaiter();
    }
    public static UniTask<T>.Awaiter GetAwaiter<T>(this AsyncOperationHandle<T> asset,CancellationToken cancellationToken)
    {
        UniTaskCompletionSource<T> completionSource = new UniTaskCompletionSource<T>();
        asset.Completed += (result) =>
        {
            cancellationToken.ThrowIfCancellationRequested();
            switch (result.Status)
            {
                case AsyncOperationStatus.None:
                    break;
                case AsyncOperationStatus.Succeeded:
                    completionSource.TrySetResult(result.Result);
                    break;
                case AsyncOperationStatus.Failed:
                    completionSource.TrySetException(result.OperationException);
                    break;
                default:
                    throw new ArgumentOutOfRangeException(result.OperationException.ToString());
            }
        };
        return completionSource.Task.GetAwaiter();
    }
    public static UniTask<T> ToUniTask<T>(this AsyncOperationHandle<T> enumerator)
    {
        return new UniTask<T>(enumerator.GetAwaiter<T>());
    }
}

を利用することで直接await Addressables.LoadAssetAsync();とさせることもできます。

参照カウントをOnDestroy時に減らす

AddressableAssetSystemでは参照カウントを使ってリソースの管理をしています。ので基本的にはReleaseを明示して開放を行います、少しでもその手間を省くためにUniRxを導入している環境では拡張メソッドを使って以下のように書くことが可能になります。

ReleaseAssetOnDestroyExtensions.cs
using UniRx.Triggers;
using UnityEngine;
using UnityEngine.ResourceManagement.AsyncOperations;
using UniRx;
using UnityEngine.AddressableAssets;

public static  class ReleaseAssetOnDestroyExtensions
{
    public static AsyncOperationHandle ReleaseAssetOnDestroy(this AsyncOperationHandle handle, Component component)
    {
        component.OnDestroyAsObservable().Subscribe(_ => Addressables.Release(handle));
        return handle;
    }
}

AssetReferenceを自分で作成する

AssetreferenceはSerializeFieldなどでUnity側から取得する以外にもguidをコンストラクタに代入することで作成することが出来ます。使い道としてはシーンのguidを取得して(Assetreference.RuntimeKey.ToString()で取得できます)保存、再起動時にそのシーンから再開ということなどが考えられます。

AssetReferenceTypeRestrictionの代替

AssetReferenceTypeRestrictionは何故か(本当に謎)廃止されてしまったのでAssetReferenceTを継承して制限するしようとなってしまいました詳しくはテラシュールブログのここにまとめてあります。

終わりに

Addressableは個人的には外部から取得できるSerializeFieldだと思っていて、若干の手間や特殊な挙動はありますがAssetBundleよりはとても敷居が低く使えるようにチューンされています皆さんもぜひ使っていきましょう!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした