🪄

【Unity】Addressablesで別のプロジェクトへリソースを転送する

2025/01/23に公開

はじめに

AddressableAssetSystemは主に、スマホゲームなどのリソースデータをアプリ本体と切り離して配信するための仕組みです。
しかしこうしたゲーム用途だけでなく、ビルド済みのUnityアプリに後からデータを追加するツールとしても使えるのではないか? と思い立ち、実験をしてみました。
既に先行事例が複数公開されていますが、AssetBundle等の運用経験がない筆者でも理解できた難易度で解説しつつ、Unity6で検証した令和最新版としてお届けします。

検証環境

  • Windows11
  • Unity6000.0.28f1
  • Addressables 2.2.2

作業手順

  1. ビルド用のプロジェクトとロード用のプロジェクトを2つ用意する。
    • プロジェクト間でUnityEditorのバージョンは揃えておく。
  2. Window/PackageManagerからAddressablesを追加する。
  3. Window/AssetManagement/Addressables/Groupsを選択するとウィンドウが表示されるので、「Create Addressables Settings」を実行する。
  4. AddressablesGroupsウィンドウが表示され、プロジェクトのAssetsフォルダ以下にはAddressableAssetsDataフォルダが追加される。
    • AddressablesGroupsウィンドウは頻繁に使うので、ドッキングしておくのがオススメ。もし閉じてしまっても3.の手順で再度表示できる。
  5. 2.~4.までの設定をビルド用とロード用両方のプロジェクトで行う。
  6. ビルド用プロジェクトでAssets/AddressableAssetsData/AddressableAssetSettingsを選択し、Inspectorビューから次の設定を適用する。
    • Catalog/Build Remote Catalogsにチェックを入れる。
    • Catalog/Build & Load PathsがRemoteになっていることを確認する。
    • Catalog/Enable Json Catalogにチェックを入れる。
  7. ビルド用プロジェクトのAssets/AddressableAssetsData/AssetGroups/Default Local Groupを選択し、Inspectorビューから次の設定を適用する。
    • Content Packing & Loading/Build & Load PathsをRemoteに切り替える。
  8. ビルド用プロジェクトのWindow/AssetManagement/Addressables/Profilesを選択し、Remoteの設定がCustomになっていることを確認し、Remote.BuildPathの内容をRemote.LoadPathにコピーする。
    これが分からず休日を溶かしたので、本稿をしたためることにした。
  9. ビルド用プロジェクトで適当なPrefab(今回ただのCube)を作成し、Inspectorの上部にある「Addressable」にチェックを入れる。
  10. AddressableGroupウィンドウにPrefabが追加されたことを確認し、Build/New Build/Default Build Scriptを実行する。
    • ビルド時にビルドレポートを表示するか確認されるので、好みで選択する。
  11. プロジェクト直下(Assetsフォルダの外側)にServerDataフォルダが作られているので、フォルダごとコピーしてロード用プロジェクトの直下にペーストする。中身はこんな感じ。
  12. ロード用プロジェクトに移り、読み込み用のサンプルスクリプトを作成する。
SpawnerByInstantiateAsync.cs
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class SpawnerByInstantiateAsync : MonoBehaviour
{
    private GameObject spawnedGameObject;

    private async void Start()
    {
        var catalogPath = Application.dataPath + "/ServerData/StandaloneWindows64/catalog_0.1.0.json";
#if UNITY_EDITOR
        // ビルド前と後でApplication.dataPathの値が変わるため
        catalogPath = catalogPath.Replace("/Assets/", "/");
#endif
        var loadCatalogHandle = Addressables.LoadContentCatalogAsync(catalogPath);
        var result = await loadCatalogHandle.Task;
        Addressables.AddResourceLocator(result);
        
        // Addressables.InstantiateAsyncでプレハブをインスタンス化する
        AsyncOperationHandle<GameObject> handle = Addressables.InstantiateAsync("Assets/Cube.prefab");

        // .Taskでインスタンス化完了までawaitできる
        spawnedGameObject = await handle.Task;

        spawnedGameObject.name = "Spawned Game Object";
    }

    private void OnDestroy()
    {
        // 使い終わったらインスタンスをリリースする
        Addressables.ReleaseInstance(spawnedGameObject);
    }
}
  1. Addressables.InstantiateAsyncの引数には、PrefabをAddressableに登録した際のPathを記入する。PathはAddressablesGroupsウィンドウからも確認できる。
  2. ロード用プロジェクトでAssets/AddressableAssetsData/AddressableAssetSettingsを選択し、Catalog/Enable Json Catalogにチェックを入れる。
  3. Scene内の適当なGameObjectにスクリプトを設定して実行すると、Prefabを作っていないはずのロード用プロジェクトでCubeがインスタンスされる。
    極めて地味な絵面だが、このCubeがプロジェクトの外からやってきた事実はなかなか感動である。トンネル効果を発見した科学者もきっとこんな気持ちだっただろう。

ポイント

  • Prefabなどのリソースデータはバイナリ化されて.bandleファイルに保存される。
  • AddressableAssetのPathと.bandleファイルの紐付けはcatalog.jsonに記述される。
  • 本来の用途では.bandleやcatalog.jsonをアップロードしたサーバーのURLなどをLoadPathに指定するが、ローカル環境で共有する場合はBuild先と同じパスにしておくことでシンプルな構成になる。
    • 実際に運用する際はServerDataフォルダではなく、プロジェクト間を跨ぐ階層のディレクトリや、オンプレサーバーのパスを使うのが現実的と思われる。

おわりに

Addressablesを用いて別のプロジェクトにリソースを転送する方法をご紹介しました。
当然ロード用プロジェクトをビルドしても動作するのですが、ビルド前には無かったアセットが出現するのは、仕組みを理解していてもどこかキツネにつままれたようです。
とりあえず基本的な使い方を把握できたので、これを業務に活用できないか色々試してみようと思います。

しかしAddressable関連ワードのタイピングは左手がしんどいですね……

参考文献

https://synamon.hatenablog.com/entry/introduction-to-addressable-asset-system
読み込み用スクリプトのベースにさせて頂きました。記事自体もAddressablesの基本的な使い方が丁寧にまとめられておりオススメです。

Discussion