概要
ゲーム開発が進み、アセット(モデル、テクスチャ、音声など)の数が増えてくると、いくつかの深刻な問題に直面します。
- メモリ使用量の増大: シーンに直接配置されたアセットや、スクリプトから直接参照されているアセットは、シーンロード時にすべてメモリに読み込まれ、不要になっても自動では解放されません。これにより、特にモバイルデバイスではメモリ不足でアプリがクラッシュする原因となります。
- ビルド時間とパッチサイズの増大: すべてのアセットがゲーム本体に含まれるため、ビルドサイズが肥大化し、少しの修正でも大きなパッチをユーザーにダウンロードさせる必要が出てきます。
- コンテンツの動的更新が困難: 新しいキャラクターやステージを追加するたびに、アプリ全体のアップデートが必要になります。
かつて、これらの問題を解決するためにResourcesフォルダが使われていましたが、これはメモリ管理が煩雑で、参照関係が追跡しにくいなど多くの問題を抱えていました。現在、これらの課題に対するUnityの公式な答えがAddressable Asset System (アドレッサブル・アセット・システム) です。
Addressablesは、アセットに「アドレス」という文字列のキーを割り当て、そのアドレスを使ってアセットを非同期で動的にロード・アンロードする仕組みです。これにより、アセットをゲーム本体のビルドから切り離し、必要な時にだけメモリに読み込み、不要になったら即座に解放するという、非常に効率的なメモリ管理が可能になります。
Addressablesの主なメリット
- メモリ管理の最適化: アセットの参照カウントを自動で管理し、どこからも参照されなくなったらメモリからアンロードしてくれます。これにより、開発者は複雑なメモリ管理から解放されます。
- コンテンツの分離と動的更新: アセットを「アセットバンドル」という単位でゲーム本体から分離し、サーバー上に配置できます。これにより、アプリのアップデートなしで、新しいコンテンツ(キャラクター、アイテム、イベントなど)を動的に配信・更新することが可能になります。
- ビルド時間の短縮: アセットがビルドから分離されるため、初期ビルドや日々のイテレーションのビルド時間が短縮されます。
Addressablesの基本的な使い方
Step 1: パッケージのインストールと初期設定
Window > Package ManagerからAddressablesパッケージをインストールします。- インストール後、
Window > Asset Management > Addressables > Groupsウィンドウを開きます。「Create Addressables Settings」ボタンをクリックすると、プロジェクトにAddressablesの設定ファイルが作成されます。
Step 2: アセットをAddressableにする
アセットをAddressable(アドレス指定可能)にするのは簡単です。
- プロジェクトウィンドウで、Addressableにしたいアセット(Prefab、テクスチャ、マテリアルなど)を選択します。
- Inspectorに表示される
Addressableチェックボックスをオンにします。
これだけで、アセットにファイルパスと同じアドレスが自動的に割り当てられ、Default Local Groupというグループに追加されます。アドレスは、Inspectorで手動で好きな文字列に変更することもできます。
Step 3: アセットをスクリプトからロードする
Addressablesのロード処理は非同期で行われます。つまり、ロードが完了するのを待つ必要があります。これには、コルーチンやasync/await構文を使用するのが一般的です。
using UnityEngine;
using UnityEngine.AddressableAssets; // AddressablesのAPIを使うために必要
using UnityEngine.ResourceManagement.AsyncOperations; // 非同期操作のために必要
public class AssetLoader : MonoBehaviour
{
// ロードしたいアセットのアドレスを文字列で指定
public string assetAddress = "Assets/Prefabs/MyCharacter.prefab";
private GameObject instantiatedObject;
private AsyncOperationHandle<GameObject> loadHandle;
async void Start()
{
// アドレスを使ってアセットを非同期ロード
loadHandle = Addressables.LoadAssetAsync<GameObject>(assetAddress);
// ロードが完了するのを待つ (await)
await loadHandle.Task;
// ロード結果を確認
if (loadHandle.Status == AsyncOperationStatus.Succeeded)
{
// ロードしたアセット(この場合はPrefab)をインスタンス化
instantiatedObject = Instantiate(loadHandle.Result);
Debug.Log("Asset loaded and instantiated successfully.");
}
else
{
Debug.LogError("Asset loading failed: " + assetAddress);
}
}
void OnDestroy()
{
// このコンポーネントが破棄される時に、ロードしたアセットの参照を解放する
// これにより、アセットが不要になったことをAddressablesシステムに伝える
if (loadHandle.IsValid())
{
Addressables.Release(loadHandle);
}
// インスタンス化したオブジェクトも破棄
if (instantiatedObject != null)
{
Destroy(instantiatedObject);
}
}
}
Addressables.LoadAssetAsync<T>()でロードを開始し、awaitで完了を待ちます。ロードが成功したら、loadHandle.Resultでロードされたアセット本体にアクセスできます。
最も重要なのは、アセットが不要になったらAddressables.Release()を呼び出して参照を解放することです。 これを忘れると、アセットはメモリに残り続けてしまいます。
まとめ
Addressable Asset Systemは、現代のUnity開発におけるスケーラブルなアセット管理の根幹をなす技術です。
Resourcesフォルダの代わりにAddressablesを使い、アセットを動的にロード・アンロードする。- アセットを
Addressableに設定し、「アドレス」というキーで管理する。 - スクリプトからは
Addressables.LoadAssetAsync<T>()で非同期にロードする。 - ロードしたアセットが不要になったら、必ず
Addressables.Release()で参照を解放する。
最初は少し複雑に感じるかもしれませんが、Addressablesを導入することで得られるメモリ効率の向上とコンテンツ管理の柔軟性は、特に中規模以上のプロジェクトにおいて計り知れないメリットをもたらします。早い段階からこのシステムに慣れておくことを強くお勧めします。