ゲーム化!tomo_manaのブログ

ゲーム化!tomo-manaのブログ

Unityでゲームを作る方法について紹介しています

Unity/C# Addressableのインストールと適用

サーバーにデータを置かない、でもAddressableは使ってみたい方向けに、Addressasble 導入の最小手順をまとめました。


Addressable に関する記事は多いのですが、それは純粋に Addressable が使いにくい(一番肝心な部分が隠蔽されている)、手順が多い、覚えることがいっぱいある、思った通りに行かない、など、いくつかの課題があるためと思います。

ただし、サーバーにデータを置かなければ、Addressable は直感的で分かりやすいと思います。


サーバーにデータを置く場合も、まずローカルのデータをResourcesからAddressableに置き換えて動作テストをして、それから「勉強」なり「サーバーにデータを置く」なりした方が、頭でっかちにならずに済むと思いました。


(サーバーにデータを置かなきゃいけなくなってから調べるケースが大半のため)サーバーにデータを置かない場合は これだけ必要という記事がまだ少ないので、本当に最小限をあくまで備忘のためにまとめました。

自分のために書いたものですが、参考になれば幸いです。

最初に

Addressable は、主にゲームに必要なデータの一部を、サーバーからダウンロードできるようにしたい時に使います。


ただ、サーバーからダウンロードしない場合でも、Resources を使っているよりは 実行ファイルの容量が少なくなる(データを圧縮してくれるので)ので、適用する価値はあります。


(Unity公式でも Resources は 非推奨 なので、サーバーを使わなくても Addressable への置き換えは検討する価値があります)

Resources - Unity Manual


なお、サーバーからダウンロードしないで(つまり全てのデータを実行ファイルに含めて)使用するなら、以下の手順だけで終わります。

インストール

パッケージマネージャからインストールできます(Verified Version※)。
※Verify でないバージョンも公開されているようですが、最初は Verify バージョンで動作を確認してからの方が良いかも。


(1) Window → Package Manager を選択

Window > Package Manager

(2) Package Manager ウィンドウ:Addressable を検索してインストール
 1) Packages: Unity Registry
 2) Addressable で検索
 3) Install ボタンを押す

Addressableのインストール


インストールが終わると、Window → Asset Management に Addressables メニューが追加されます。

追加されるメニュー(Window → AssetManagement → Addressables)

適用

Addressable で最低限必要な設定は以下の通りです。

機能 やること
Groups グループ分け
Profile サーバーの設定など
Settings 追加設定など


サーバーにデータを置かない場合は、Groups のみ設定します。

Addressables Settings の作成

最初に、Addressable Settings を作成します。

1) Window → Asset Management → Addressables → Groups を選択

Addressables Groups(Window → AssetManagement → Addressables → Groups)

2) Create Addressables Settings ボタンを押す

Create Addressable Settings

Addressables Settings が作られると、Groups ウィンドウにリソースの一覧が表示されます。

Addressables Groups ウィンドウ

Resources を使用している場合、Built In Data の Resources に登録されます。


なお、Addressables Settings が作られるまで、Groups 以外のメニューは使用できません(以下のエラーが返ります)。

先に Addressable Settings を作ってね

Addressables Groups への登録

最初は Addressables への登録の仕方が分からないと思うので、Resources フォルダに入れておいたデータを Addressables に登録するところからやってみます。


Addressables がインストールされた状態では、Inspector の先頭に Addressable チェックマークが追加されます。

(1) Projectウィンドウから、Addressables Groups に登録したいデータを選択
(2) Inspectorウィンドウで、Addressable にチェックを付ける

Addressables への登録(Inspector → Addressable にチェックを付ける)

(3) 以下のダイアログが表示された場合は、Yes ボタンを押す

Resourcesフォルダから削除・移動します

(4) Addressables Groups に登録されたことを確認する

Addressables Group に登録された

※Resources にファイルを置いていた場合は、Resources フォルダから Resources_moved フォルダに移動します(詳細確認していませんが、Resources_moved フォルダは、多分Resources があったフォルダと同じ階層に作られます)。

※注意:Addressables Groups は複数作成できます。Addressable にチェックを付けた時、(Default) に設定された Addressables Groups に登録されます(別記事)


(5) Addressables Groups の左側のパスが、プログラムからアクセスするパスになります。必要に応じて、Addressable Name を変更します(以下の例ではフォルダパスを削除しました)。

 1) Addressables Groups のリスト、または Projectウィンドウから、対象のリソースを選択して、Inspectorウィンドウ上でリソースが選択された状態にします(ここはいつものリソースを選択する手順です)
 2) Addressable チェックマークの右にある空欄に、プログラムからアクセスするパスを入力
 3) Addressable Groups のリスト上で、左側のパスが変更されたことを確認

Addressable Name のリネーム(Inspector)


一度やってみると、Addressables に登録するために、特別なリソース用のフォルダを作らなくてもいいことが分かります。(必ずしも Resources_moved というフォルダ名にしなくてもいい)

Addressables Groups のビルド

Addressables Groups のビルドは、プログラムのコンパイル時に実行してくれないので、独自に行う必要があります。(ここがちょっと分かりにくいところです)

Addressabes Groups ウィンドウ:Build → New Build → Default Build Script を選択

Addressables Groups のビルド

少し時間かかりますが、ビルドが行われて、カタログが作成されます。

ビルド中表示(少し時間かかります)

※プラットフォーム毎に作成されるデータが変わるので、プラットフォームを変更した時には、必ず先にビルドを実行して下さい。

以下は、WebGLプラットフォーム の場合を示します(まだ他のプラットフォーム試してないので)

Addressablesリソース(Asset Bundle)の展開場所

どのフォルダに、どのようなフォーマットで作成されるかは、プラットフォームによって異なるのかもしれないのですが、カタログファイルとAsset Bundleファイルが作られます。

LocalLoadPath の UnityEngine.AddressableAssets.Addressables.RuntimePath は Library/com.unity.addressables/aa/WebGL を指すので、LocalBuildPath も LocalLoadPath も、いずれも AssetBandle ファイルのあるフォルダを指しています。

(AssetBundle については別の記事に書こうと思いますが、Addressables Group のデータ部分は AssetBandle 形式で保存されます。AssetBundle は以前からあるデータ形式のようです。)

Resources.Load を置き換える場合(コード)

Addressables Groups に登録したリソースを Resources.Load() で呼び出していなければ、ここまでで実行テストができます。

Resources.Load() で呼び出していた場合、ロード処理を Addressable に置き換える必要があります。ロード処理は通常 Addressables.LoadAssetAsync(Object key) を使用します。


以下にコードサンプルを示します。先ほどの例で出てきた "glitter.png" というファイルを表示する場合は以下のようになります。

using System.Collections;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

// cited from https://tomo-mana.hatenablog.com/
public class LoadSample : MonoBehaviour
{
    // Resources
    public static Sprite LoadSprite(string path)
    {
        Texture2D texture = Resources.Load(path) as Texture2D;
        return Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
    }

    // Addressable
    private AsyncOperationHandle<Texture2D> handleHold;
    Sprite spriteWork;

    public IEnumerator LoadSpriteAsyncCoroutine(string path)
    {
        AsyncOperationHandle<Texture2D> handle;

        try
        {
            handle = Addressables.LoadAssetAsync<Texture2D>(path);  // ロード処理
        }
        catch (InvalidKeyException e)
        {
            Debug.Log($"{e}");
            yield break;
        }

        while (!handle.IsDone)
        {
            yield return null;
        }

        handleHold = handle;

        if (handle.Status == AsyncOperationStatus.Succeeded)
        {
            Texture2D texture = handle.Result;
            spriteWork = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), Vector2.zero);
        }
    }

    void Start()
    {
        // memo:
        // Resources の場合はファイル名
        // 
        // Addressable の場合は Addressable Groups の左側のパス
        // (LocalLoadPath は自動で付けてくれる)

        // Resources の場合
//        string path = "glitter";
//      LoadSprite(path);

        // Addressable の場合
        // 左側のパスに拡張子名を入れていない場合は、拡張子名は不要です
        string path = "glitter.png";
        StartCoroutine(LoadSpriteAsyncCoroutine(path));
    }

    public void OnDestroy()
    {
        Addressables.Release(handleHold);
    }
}

いくつかクセがあります。
● Addressables.LoadAssetAsync(Object key) は非同期のため、リソースを使用する側にも待ち処理を入れる必要があります(LoadAsset(Object key) というインターフェースもあるようなのですが、中でどのように待っているか分からないので、通常は非同期処理を使用します)

● handle.Result は、Addressables.Release( handle ) をコールするまでの間は参照可能です。C++ネイティブ領域への参照を持っているらしく、ガベージコレクタで勝手にメモリ開放されません。リソースデータ を使い終わったら必ず handle を開放します。

WebGL では、ロード待ち処理 await handle が使用できません(中でTaskを使用していますが、WebGLのようなシングルスレッド環境では動作できません)。コルーチンかUniRx/UniTask を使用して、handle.isDone フラグが立つまで自作ルーチン内で待つ方法を使用します。yield return handle は確認中です。


(以下は別記事でまとめます)
●予備知識(StreamingAsset、AssetBundle、AssetDataBase)
●グループを分ける(ローカル分割、サーバー)
●unityroomで使用する
●InvalidKeyException

参考リンク

note.com