mcpField
U
Unity Addressables

Unity Addressables

github.com/juliankerignard開発852 回インストール32 週間前に更新
リポジトリ

Unity Addressables について

非同期ロード、グループ管理、メモリ管理、リモートコンテンツを必要とする開発者向けに、Unity Addressables によるアセット管理を解説するスキルです。Resources.Load からの移行や、メモリリークを防ぐハンドルの解放も扱います。

主な機能

  1. 01アセットの非同期ロード
  2. 02グループとラベルによる整理
  3. 03進捗付きアセットの先行ロード
  4. 04ハンドルと参照カウントの管理
  5. 05Addressables によるシーンロード
  6. 06Resources.Load からの移行

活用シーン

  1. 01Unity プロジェクトでアセットを必要時にロード
  2. 02任意コンテンツやシーン別コンテンツの管理
  3. 03ハンドル解放によるメモリリーク防止
  4. 04既存の Resources.Load 利用箇所を Addressables に移行

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/juliankerignard/unity-skills --skill unity-addressables

インストール後、Claude Code で/unity-addressablesを入力して読み込まれたか確認します。

同梱ファイルreferences/addressables-patterns.md

詳細

Unity Addressables

このスキルでできること

非同期アセット読み込み、グループ構成、メモリ管理、リモートコンテンツ(CDN/DLC)に Addressables システムを使用する方法を説明します。Resources.Load からの移行、進捗表示付きのプリロード、参照カウント、メモリリークを防ぐための解放パターンについて解説します。

前提条件

  • Package Manager からインストールしたパッケージ com.unity.addressables

クイックスタート

  1. パッケージをインストールします:Window > Package Manager > Unity Registry > Addressables
  2. Window > Asset Management > Addressables > Groups を開きます
  3. アセットを「Addressable」としてマークします(Inspector のチェックボックス)
  4. 論理グループに整理します(機能別、シーン別、ダウンロード別)
  5. Addressables.LoadAssetAsync<T> で読み込みます

判断フローチャート

Comment charger cet asset ?
|
+-- Toujours en memoire, reference directe dans l'Inspector ?
|   --> Reference directe [SerializeField] (pas besoin d'Addressables)
|
+-- Charge a la demande, connu au compile-time ?
|   --> AssetReference dans l'Inspector + LoadAssetAsync
|
+-- Charge dynamiquement par label/nom ?
|   --> Addressables.LoadAssetsAsync avec label
|
+-- Contenu telechargeable (DLC, patches) ?
|   --> Remote group + catalog update
|
+-- Migration depuis Resources.Load ?
    --> Marquer les assets comme Addressable, remplacer Resources.Load par LoadAssetAsync

ステップバイステップガイド

Step 1:グループの構成
  • 機能別グループ:Characters、Levels、UI、Audio
  • ダウンロード別グループ:Core(ビルドに含める)、Optional(ダウンロード可能)
  • シーン単位で読み込む場合はシーン別グループ
  • 大きすぎるグループ(> 50 MB)は避け、用途別のサブグループに分割します
  • ラベルを使って複数のグループにまたがるアセットにタグを付けます(level1、boss、tutorial)
Step 2:ハンドルを使った非同期読み込み
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class AssetLoader : MonoBehaviour
{
    [SerializeField] private AssetReference prefabRef;
    private AsyncOperationHandle<GameObject> handle;

    public async Awaitable<GameObject> LoadAndInstantiateAsync()
    {
        handle = Addressables.LoadAssetAsync<GameObject>(prefabRef);
        await handle.Task;

        if (handle.Status == AsyncOperationStatus.Succeeded)
            return Instantiate(handle.Result);

        Debug.LogError($"Failed to load: {prefabRef}");
        return null;
    }

    private void OnDestroy()
    {
        // CRITIQUE: toujours release le handle
        if (handle.IsValid())
            Addressables.Release(handle);
    }
}

重要なポイント:

  • Inspector で AssetReference を使うと、マジックストリングを避けられます
  • await handle.Task で読み込み完了を待ちます
  • handle.Result を使用する前に、必ず handle.Status を確認します
  • メモリリークを防ぐため、OnDestroy で Release を呼び出します
Step 3:ラベルによる読み込み
public class LabelLoader : MonoBehaviour
{
    [SerializeField] private AssetLabelReference labelRef;
    private AsyncOperationHandle<IList<GameObject>> handle;

    public async Awaitable<IList<GameObject>> LoadAllAsync()
    {
        handle = Addressables.LoadAssetsAsync<GameObject>(labelRef, null);
        await handle.Task;

        if (handle.Status == AsyncOperationStatus.Succeeded)
            return handle.Result;

        Debug.LogError($"Failed to load label: {labelRef}");
        return null;
    }

    private void OnDestroy()
    {
        if (handle.IsValid())
            Addressables.Release(handle);
    }
}
Step 4:Resources.Load から Addressables への移行
// AVANT (synchrone, tout en memoire au build)
var prefab = Resources.Load<GameObject>("Enemies/Goblin");

// APRES (async, charge a la demande)
var handle = Addressables.LoadAssetAsync<GameObject>("Enemies/Goblin");
await handle.Task;
var prefab = handle.Result;
// ... utiliser prefab ...
Addressables.Release(handle);

移行手順:

  1. アセットを Resources/ フォルダーの外に移動します
  2. 各アセットを Addressable としてマークします(Inspector のチェックボックス)
  3. アドレスが以前の Resources/ パスと一致していることを確認します
  4. Resources.Load<T>(path) を Addressables.LoadAssetAsync<T>(address) に置き換えます
  5. アセットが不要になったら Release() を追加します
  6. 移行が完了したら Resources/ フォルダーを削除します
Step 5:Addressables シーン
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.ResourceProviders;

public class SceneLoader : MonoBehaviour
{
    [SerializeField] private AssetReference sceneRef;
    private AsyncOperationHandle<SceneInstance> sceneHandle;

    public async Awaitable LoadSceneAsync()
    {
        sceneHandle = Addressables.LoadSceneAsync(sceneRef);
        await sceneHandle.Task;
    }

    public async Awaitable UnloadSceneAsync()
    {
        if (sceneHandle.IsValid())
        {
            await Addressables.UnloadSceneAsync(sceneHandle).Task;
        }
    }
}

厳守事項

  • アセットが不要になったら、必ず Addressables.Release(handle) を呼び出します
  • Inspector では必ず AssetReference を使います(アドレスを文字列で直接指定しないでください)
  • 読み込み失敗を必ず処理します(handle.Status)
  • InstantiateAsync で生成したオブジェクトには、Destroy() ではなく必ず Addressables.ReleaseInstance() を使います
  • 新規プロジェクトでは Resources.Load を絶対に使用しないでください(Addressables を使用します)
  • ハンドルを解放せずに保持することは絶対にしないでください(メモリリークの原因になります)
  • 参照カウントを使わずに同じアセットを二度読み込むことは絶対にしないでください
  • 参照の型を指定するには、AssetReferenceT<T>(AssetReferenceGameObject、AssetReferenceSprite など)を優先して使用します
  • Inspector では、ラベル文字列よりも AssetLabelReference を優先して使用します

関連スキル

  • /perf-audit:メモリリークと未解放アセットを検出します
  • /unity-build-config:コンテンツとリモートカタログをビルドします
  • /unity-code-gen:ローディングシステムとアセットマネージャーを生成します

トラブルシューティング

問題解決策
"InvalidKeyException"アドレスまたはラベルが存在しません。Addressables Groups ウィンドウで確認してください
メモリリークRelease() の呼び出し忘れです。Addressables Profiler(Event Viewer)を使用してください
ビルドにアセットが含まれないアセットがどのグループにも属していないか、グループがビルドに含まれていません
読み込みが遅いグループが大きすぎます。用途別にサブグループに分割してください
"Cannot instantiate"アセットがプレハブではないか、読み込みに失敗しています(Status を確認してください)
"Exception during init"Addressables が初期化されていません。まず Addressables.InitializeAsync() を呼び出してください
アセットの重複1 つのアセットが複数のグループに属しています。Build Report を使用して検出してください
リモートカタログが最新でない起動時に CheckForCatalogUpdates を呼び出し、その後 UpdateCatalogs を呼び出してください

コメント