はじめに
Unity 6.6 で、AssetBundle の後継となる Content Directories が登場しました。この記事では、アセットを実行時に読み込む方法を、配置方法と読み込みコードつきで比較します。AssetBundle を直接使う方法は、関係図と比較表で扱います。
- Resources
- Addressables(AssetBundle バックエンド)
- Content Directories(コードから直接)
これらは同じ階層に並ぶ選択肢ではありません。Resources と AssetBundle と Content Directories は「保存・ロード形式」、Addressables はその上に乗る「管理レイヤー」です。最後に、Addressables 4.x と Unity 7 で予定されていることにも触れます。
環境
- Unity 6000.6.0f1
- Addressables 2.11.2
プロジェクト構成
方法ごとにフォルダを分けて、それぞれ別の画像を読み込んでいます。
注意:Content Directories は2026年に登場したばかりの機能です。仕様は今後変わる可能性があるので、最新の公式ドキュメントも併せて確認してください。
1. Resources
Resources という名前のフォルダに置くだけで、文字列のパスで読み込める最も古くシンプルな方式です。ビルド作業は不要です。
〇 配置方法
-
Assets以下にResourcesフォルダを作る(階層のどこにあってもよく、複数あってもよい) - 読み込みたいアセットを入れる。今回は
Assets/Resources/Character/CharacterImage_0001
〇 読み込み方法
パスは Resources フォルダからの相対パスで、拡張子は付けません。
using UnityEngine;
/// <summary>
/// リソース読み込みテスト
/// </summary>
public class TestResourceLoad : MonoBehaviour {
/// <summary> 画像描画 </summary>
[SerializeField, Header("画像描画")]
SpriteRenderer spriteRenderer;
/// <summary>
/// 起動時
/// </summary>
void Start() {
var sprite = Resources.Load<Sprite>("Charcter/CharacterImage_0001");
spriteRenderer.sprite = sprite;
}
}
非同期で読み込むときは Resources.LoadAsync を使います。
using UnityEngine;
/// <summary>
/// リソース読み込みテスト
/// </summary>
public class TestResourceLoad : MonoBehaviour {
/// <summary> 画像描画 </summary>
[SerializeField, Header("画像描画")]
SpriteRenderer spriteRenderer;
/// <summary>
/// 起動時
/// </summary>
async void Start() {
var request = Resources.LoadAsync<Sprite>("Charcter/CharacterImage_0001");
await request;
spriteRenderer.sprite = request.asset as Sprite;
}
}
〇 解放
個別のアセットを解放する API は限られており、基本は Resources.UnloadUnusedAssets() で、どこからも参照されなくなったアセットをまとめて解放します。
〇 特徴と欠点
- Resources フォルダ内のものは、参照の有無に関係なくすべてビルドに含まれる
- 起動時にインデックス構築が走るため、アセット数が増えると起動時間が延びる
- 解放のタイミングを細かく制御しにくい
- リモート配信や、アプリ更新なしのコンテンツ差し替えはできない
Unity 自身も、プロトタイプや、起動時に必ず使う少量のアセット以外では推奨していません。
2. Addressables(AssetBundle バックエンド)
Addressables は、AssetBundle の面倒な部分(バンドルの場所、依存関係、参照カウント)を肩代わりする管理レイヤーです。コードはアドレスを指定するだけで済みます。
〇 配置方法
- Package Manager から Addressables をインストールする
- Window > Asset Management > Addressables > Groups を開き、Create Addressables Settings を押す(
AddressableAssetsDataが生成される) - 読み込みたいアセットの Inspector で Addressable にチェックを入れる(または Groups ウィンドウにドラッグ)
- アドレス(例:
AssetBundleTestLoad)を必要に応じて短く変更する
どのバンドルに入るかはグループで決まり、グループ設定の Bundle Mode(Pack Together / Pack Separately など)で分け方を選べます。
〇 ビルド方法
Groups ウィンドウの Build > New Build > Default Build Script でビルドします。エディタでビルド結果を使って確認するときは、Play Mode Script を Use Existing Build にします。
〇 読み込み方法
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
/// <summary>
/// リソース読み込みテスト
/// </summary>
public class TestResourceLoad : MonoBehaviour {
/// <summary> 画像描画 </summary>
[SerializeField, Header("画像描画")]
SpriteRenderer spriteRenderer;
/// <summary> アセットバンドル読み込みハンドル </summary>
AsyncOperationHandle<Sprite> loadHandle;
/// <summary>
/// 起動時
/// </summary>
async void Start() {
loadHandle = Addressables.LoadAssetAsync<Sprite>("AssetBundleTestLoad");
var sprite = await loadHandle.Task;
spriteRenderer.sprite = sprite;
}
/// <summary>
/// 破棄時
/// </summary>
void OnDestroy() {
// 読み込みごとに Release する(参照カウントで管理)
if (loadHandle.IsValid())
Addressables.Release(loadHandle);
}
}
アドレスの文字列の代わりに、Inspector で AssetReference を割り当てる方法もあります。
〇 特徴
- バンドルの場所解決、依存バンドルの読み込み、参照カウントによる解放を自動でやってくれる
- アセットがローカルにあっても CDN 上にあっても、同じコードで読み込める
- ただし裏側は AssetBundle なので、ロード・解放・ダウンロードの最小単位はバンドルのまま。あるアセットを Release しても、同じバンドルの別アセットが使われていればバンドルはメモリに残る
3. Content Directories(コードから直接)
Content Directories は、Unity 6.6 で追加された AssetBundle の後継です。アセットにバンドル名を付ける代わりに、ルートアセット(ScriptableObject)から参照されたものがビルドに含まれます。読み込みは Loadable<T> を通じて、アセット単位で行います。
〇 AssetBundle との手順の違い
| 作業 | AssetBundle | Content Directories |
|---|---|---|
| 何を含めるか決める | アセットにバンドル名を付ける | ルートアセットから参照する |
| ビルド | BuildPipeline.BuildAssetBundles |
BuildPipeline.BuildContentDirectory |
| 読み込みの準備 |
AssetBundle.LoadFromFile で依存バンドルも含めて開く |
ContentLoadManager.RegisterContentDirectory で登録 |
| アセットを読み込む | AssetBundle.LoadAsset |
Loadable<T>.Load / LoadAsync
|
| 解放 |
AssetBundle.Unload でバンドルごと |
Loadable<T>.Release でアセットごと |
〇 配置方法
1. ルートアセットのクラスを作る
Assets/Script/CharacterContent.cs に、読み込みたいアセットへの参照を Loadable<T> で持つ ScriptableObject を作ります。
using Unity.Loading;
using UnityEngine;
/// <summary>
/// コンテンツのルート
/// </summary>
[CreateAssetMenu(fileName = "CharacterContent", menuName = "Content/Character Content")]
public class CharacterContent : ScriptableObject {
/// <summary> ビルドには含まれるが、Load するまでメモリに載らない参照 </summary>
public Loadable<Sprite> resource;
}
ルートアセットは、RegisterContentDirectory で登録した時点で自動的にメモリに読み込まれます。ルートアセットが直接参照(public Sprite characterImage;)しているアセットも、そのとき一緒に読み込まれ、個別には解放できません。Loadable<T> で参照しておけば、Load を呼ぶまでは読み込まれず、Release で個別に解放できます。そのため、大きなアセットは Loadable<T> で参照するのが推奨です。
2. ルートアセットを作って割り当てる
-
Assets/Contentで右クリックし、Create > Content > Character Content を選ぶ - 作成した
CharacterContentを選択し、Inspector の resource にCharacterImage_0003を割り当てる
ルートアセットから参照されたアセットは、依存先も含めて自動でビルドに入ります。ルートアセットは基本的に1つで十分で、追加コンテンツパックなどを分けたいときだけ増やします。
ルートアセットは「ビルドに何を入れるか」と「実行時にどこから辿るか」を決める入口で、バンドルのような読み込みの単位ではありません。ルートアセットに100個の Loadable<T> を並べても、読み込まれるのは Load したものだけです。
なお、パス文字列でアセットを直接読み込む API はありません。文字列で引きたい場合は、キーと Loadable<T> の一覧を持つ ScriptableObject をルートアセットにします。
〇 ビルド方法
Assets/Script/Editor にビルド用スクリプトを置きます。プレイヤーに同梱するコンテンツは、StreamingAssets のサブフォルダに出力します。
using UnityEditor;
using UnityEditor.Build.Reporting;
using UnityEngine;
public static class ContentDirectoryBuilder {
/// <summary>
/// ContentDirectory ビルド
/// </summary>
[MenuItem("Build/Build Content Directory")]
public static void Build() {
var parameters = new BuildContentDirectoryParameters {
outputPath = "Assets/StreamingAssets/CharacterContent",
rootAssetPaths = new[] { "Assets/Content/CharacterContent.asset" },
options = BuildContentOptions.None,
};
BuildReport report = BuildPipeline.BuildContentDirectory(parameters);
if (report.summary.result == BuildResult.Succeeded)
Debug.Log($"Content directory built to: {parameters.outputPath}");
}
}
メニューの Build > Build Content Directory を実行すると、出力先に次のファイルができます。
-
.cf:シリアライズされたオブジェクト -
.resS:テクスチャやメッシュのデータ -
.resource:音声・動画のデータ -
<ハッシュ>.json:ビルドマニフェスト(読み込みに必要な情報) -
BuildManifestHash.txt:現在のマニフェストのハッシュ
ファイル名は中身のハッシュになります。BuildContentOptions.UseArchive を付けると、まとめて content0.archive 1つに格納されます。
〇 読み込み方法
コンテンツディレクトリを登録し、ルートアセットを取得して、その Loadable<T> を読み込みます。
using System.IO;
using Unity.Loading;
using UnityEngine;
/// <summary>
/// リソース読み込みテスト
/// </summary>
public class TestResourceLoad : MonoBehaviour {
/// <summary> 画像描画 </summary>
[SerializeField, Header("画像描画")]
SpriteRenderer spriteRenderer;
/// <summary> ContentDirectoryハンドル </summary>
ContentDirectoryHandle directory;
/// <summary> 読み込みリソース </summary>
Loadable<Sprite> resource;
/// <summary>
/// 起動時
/// </summary>
async void Start() {
var path = Path.Combine(Application.streamingAssetsPath, "CharacterContent");
directory = ContentLoadManager.RegisterContentDirectory(path);
var root = ContentLoadManager.GetRootAssets<CharacterContent>(directory)[0];
resource = root.resource;
await resource.LoadAsync();
if (resource.Status == LoadableStatus.Loaded)
spriteRenderer.sprite = resource.Target;
}
/// <summary>
/// 破棄時
/// </summary>
void OnDestroy() {
resource?.Release();
ContentLoadManager.UnregisterContentDirectory(directory);
}
}
同期で読み込むときは resource.Load() の直後に Target を参照します。
〇 注意点
-
RegisterContentDirectoryはエディタでは Play モード中のみ使える。Play モード外で呼ぶと例外になる - 登録したディレクトリから辿った
Loadable<T>は、常にビルド済みのコンテンツから読み込まれる。アセットを変更したら、コンテンツを再ビルドする -
UnregisterContentDirectoryの前に、読み込んだものをすべてReleaseする。Play モードで登録した場合は、Play モード終了前に解除する -
Loadable<T>の1インスタンスが持てる参照は1つ。複数の呼び出し元が同じアセットを使うなら、LoadableObjectIdから呼び出し元ごとにインスタンスを作る(同じインスタンスを共有すると、最初の Release で全員分が解放される) - 循環参照があるアセット同士は、まとめて1単位で読み込まれる
〇 仕組みの特徴
- アーティファクト単位:メッシュやテクスチャなど個々のアーティファクトを、独立してロード・アンロードできる。FBX 1つから複数のアーティファクトが生成されることもある
- 重複の自動排除:依存はアセット単位で追跡され、重複は暗黙的に排除される。重複回避のためのグループ設計が不要になる
- コンテンツアドレス:git と同様に、ファイル名は中身のハッシュ。同じ中身なら同じファイルになる
- インクリメンタルビルド:前回から変わった部分だけを再ビルドするので、2回目以降は速い(クリーンビルドは AssetBundle より遅いこともある)
- 完全非同期ロード:読み込みもデシリアライズも非同期で、並列性を活かせる
〇 実績:Slime Rancher 2
Unity の公式ブログでは、Slime Rancher 2での比較が紹介されています。既存の Addressables プロジェクトから、コード変更なしで切り替えた結果です。
| 項目 | AssetBundle | Content Directories |
|---|---|---|
| インクリメンタルビルド | 約32分 | 約3分 |
| プレイヤーサイズ | 4 GB | 2.88 GB |
| 起動からゲームプレイまで | 45秒 | 30秒 |
出典:Content Directories: beyond the AssetBundle(Unity Blog)
〇 最大の制約:ローカルのみ
Unity 6.6 時点では、プレイヤーに同梱するローカルコンテンツのみが対象です。リモート配信や、インストール後のダウンロードをしたい場合は、自前で配布の仕組みを作るか、AssetBundle を使う必要があります。
4つの方法の関係と比較
Resources・AssetBundle・Content Directories は、それぞれ API と保存形式がセットになった仕組みです。Addressables だけは管理レイヤーで、保存形式として AssetBundle を使い、4.x では Content Directories も選べるようになります(現時点はPre-release版が必要)。
| 項目 | Resources | AssetBundle(直接) | Addressables(AssetBundle) | Content Directories(直接) |
|---|---|---|---|---|
| 含め方 | Resources フォルダに置く | バンドル名を付ける | Addressable にしてグループに入れる | ルートアセットから参照する |
| ビルド | 不要 | BuildAssetBundles |
Groups ウィンドウからビルド | BuildContentDirectory |
| 読み込み | Resources.Load |
LoadFromFile + LoadAsset
|
LoadAssetAsync |
RegisterContentDirectory + LoadAsync
|
| 解放 | UnloadUnusedAssets |
Unload(バンドル単位) |
Release(参照カウント、バンドル単位) |
Release(アセット単位) |
| 依存関係 | 全部ビルドに入る | 自分で読み込む | 自動 | 自動、重複も排除 |
| リモート配信 | 不可 | 可能 | 可能 | 不可(Unity 7 世代で予定) |
| 対応バージョン | 全バージョン | 全バージョン | Addressables パッケージ | Unity 6.6 以降 |
選び方の目安
| 状況 | おすすめ |
|---|---|
| Unity 6.6 以降で、プレイヤー同梱のコンテンツだけ扱う | Content Directories(直接) |
| リモート配信や DLC が必要 | Addressables(AssetBundle) |
| すでに Addressables で運用している | そのまま継続し、Addressables 4.x で Content Directories に切り替える |
| バンドルの構成を自分で完全に制御したい | AssetBundle(直接) |
| プロトタイプや、起動時に必ず使う少量のアセット | Resources |
Content Directories と AssetBundle の混在は、共通の依存アセットが両方でビルドされて重複するため、基本的には避けるのが推奨です。ただし「ローカルは Content Directories、リモートは AssetBundle」という使い分けは、公式にも選択肢として挙げられています。
今後:Addressables 4.x と Unity 7
〇 Addressables 4.x で Content Directories が使えるようになる
Addressables 4.x では、グループのビルド方式として Content Directory を選べるようになります。Groups ウィンドウでグループを右クリックし、Convert schema(s) to Content Directory を選ぶだけで切り替わり、AssetBundle に戻すこともできます。
-
LoadAssetAsync、Release、AssetReferenceなどのコードはそのまま使える - 方式はグループごとに決まる。Content Directory のグループはアーティファクト単位、AssetBundle のグループはバンドル単位で動く
- リモートのロードパスを使うグループは変換できず、AssetBundle のまま
- 重複回避のためだけに Addressable にしていたアセットは、登録を外してよくなる
先ほどの Slime Rancher 2 の結果も、この Addressables 経由の切り替えによるものです。
ただし、Addressables 経由で Content Directories を使うには、現時点ではPre-release版の Addressables が必要です。筆者の環境(Unity 6000.6.0f1)では、Package Manager に表示されるのは 2.11.2 のみで、4.0.2 や 3.1.1 を名前で指定してもインストールできませんでした。なお Unity 6.7 のパッケージ一覧では 4.1 系がリリース版として掲載されています。(画像のものは Pre-release版でダウンロードしたものです。 )
〇 Unity 7 でリモート配信に対応する可能性
Unity は Content Directories を、コンテンツ周りを全面刷新する取り組みの第一段階と位置づけています。Unity 7 世代でリモートコンテンツにも拡張する予定で、詳細は2027年に共有するとしています。
公式ブログでは、端末に足りないアーティファクトだけを取得する仕組みが示されています。マニフェストがハッシュで管理されているので、変わったものだけを判別できます。今までの「テクスチャ1枚の修正でも、それを含むバンドル全体を再ダウンロード」が、「変わったファイルだけ取得」になるイメージです。
一方で、次の点はまだわかっていません。
- リモートの Content Directories が Addressables のグループ経由で提供されるのか、別の仕組みになるのか
- Unity 7 世代でも AssetBundle のリモート配信が並行して残るのか
- Content Directory のグループと AssetBundle のグループが互いに依存している場合の扱い
今のうちに Addressables の API で書いておけば、バックエンドの切り替えだけで移行しやすい構成になります。
まとめ
- Resources:置くだけで使えるが、全部ビルドに入り制御も粗い。試作向け
- AssetBundle:コードから直接使える。リモート配信できるが、ロード・解放・ダウンロードはバンドル単位
- Addressables:AssetBundle の面倒な管理を肩代わりする管理レイヤー。4.x では Content Directories もバックエンドに選べる
- Content Directories:Unity 6.6 の新基盤。ルートアセットと
Loadable<T>で、アセット単位にロード・解放できる。現時点はローカルのみ
Content Directories は登場したばかりなので、本番投入前には検証用のプロジェクトで、対象プラットフォームでの動作を確認することをおすすめします。
参考資料
- Content Directories: beyond the AssetBundle(Unity Blog)
- Introduction to content directories(Unity 6.6 Manual)
- Create content directories(Unity 6.6 Manual)
- Reference content in a content directory(Unity 6.6 Manual)
- ContentLoadManager.RegisterContentDirectory(Scripting API)
- Loadable<T>(Scripting API)
- Convert Addressables projects to content directories(Addressables 4.0)
- Addressables Changelog
- Addressables(Unity 6.7 パッケージ一覧)







