これはゲーム開発エンジン Unity に関する記事です。
この記事は、
https://docs.unity3d.com/Packages/com.unity.addressables@1.1/manual/AddressableAssetsDevelopmentCycle.html
に書かれている内容を日本語に翻訳したものです。
※この記事では、Addressable Asset System をAASと省略して書きます。
アドレッサブル・アセットが持つメリットのひとつは、コンテンツの配置、構築、ロードの方法を切り離すことです。通常、アセットを管理する上で、これらは強く結びついています。
Resources フォルダ内にコンテンツを配置した場合、ベースアプリケーションをビルドし、Resources.Load メソッド使用時にリソースへのパスを与えることによってコンテンツをロードしなければいけません。それ以外のコンテンツにアクセスするには、直接参照を使うか、アセットバンドルを使うしかありません。
アセットバンドルを使う場合、パスとロードとコンテンツを構築する仕組みを結び付けて再度ロードする必要があります。
ネットワークを通してアセットバンドルにアクセスするか、他のアセットバンドルと依存関係がある場合、全てのアセットバンドルに対してロード、アップロード、ダウンロードを管理するコードを書く必要があります。
アセットにアドレスを設定することで、そのアドレスを使ってロードができるようになります。プロジェクトがどこにあっても、どのようにアセットを構築しても関係ありません。アドレッサブル・アセットのパスやファイル名を変更しても問題ありません。ロードを行うコードを一切変更することなく、Resources フォルダから、ローカルのビルド先から、それ以外のビルド先(ネットワークを通じてアクセスするものを含む)からアドレッサブル・アセットを移動させることができます。
スキーマはデータのセット(集合、複数のデータを集めたもの)を定義します。インスペクターでアセットグループをスキーマに割り当てることができます。スキーマのセットはどのようにそのコンテンツをビルドするかを定義するグループに割り当てます。例えば、パックモードでビルドする際、BundleAssetGroupSchema スキーマを割り当てたグループは、アセットバンドルのソース(おおもと)として機能します。
ビルドスクリプトとは、プロジェクト内の IDataBuilder インターフェースを実装した ScriptableObject アセットのことを表しています。ユーザーは独自のビルドスクリプトを作成し、インスペクターで AddressableAssetSettings オブジェクトに追加することができます。Addressables ウィンドウ(Window > Asset Management > Addressables)で、ビルドスクリプトを選択し、ドロップダウンオプションを選ぶ。
現状、フルアプリケーションビルドをサポートするための3つのスクリプトと、エディターで繰り返し使う3つのプレイモードスクリプトを実装しています。
アドレッサブルアセットのパッケージは、アプリ開発を加速させるのを手助けするためプレイモードデータを生成する3つのビルドスクリプトを持っています。
ファストモード(BuildScriptFastMode)はゲームのフロー全般を通して、ゲームの起動を速くします。ファストモードは、データ解析やアセットバンドルの生成を行うことなく、素早くデータを走査するためにアセットデータベースからアセットを直接読み込みます。
バーチャルモード(BuildScriptVirtualMode)は、アセットバンドルを生成することなく、依存関係とデプロイ用のコンテンツの解析を行います。アセットは、アセットバンドルを通してロードされたかのように、ResourceManagerを介してアセットデータベースからロードされます。ゲームプレイ中にアセットバンドルがいつロードもしくはアンロードされたのかを見るため、アドレッサブルプロファイラウィンドウ(Window > Asset Management > Addressable Profiler)にアセットの使用方法を表示します。
バーチャルモードはロード方法のシミュレーションと製品をリリースするための正しいバランスを探すためにコンテンツグループの調整を手助けします。
パックドプレイモード
パックドプレイモード(BuildScriptPackedPlayMode)は既にビルドしたアセットバンドルを使います。このモードは、ほぼデプロイされたアプリのビルド内容と同じですが、それとはまた別にデータをビルドする必要があります。アセットを変更していないなら、このモードはプレイモードで何のデータも処理しないため最速です。アドレッサブルズウィンドウ(Window > Asset Management > Addressables)で Build > Build Player Content を選択するか、スクリプトで AddressableAssetSettings.BuildPlayerContent() メソッドを使って、このモード用にコンテンツをビルドしなければいけません。
正しいスクリプトを選ぶ
プレイモードスクリプトを適用するには、アドレッサブルズウィンドウメニュー(Window > Asset Management > Addressables)から、プレイモードスクリプトを選択し、ドロップダウンオプションから選択します。各モードはそれぞれ独自の時間と開発およびデプロイ中の場所を持ちます。以下のテーブルは開発サイクルのステージを表し、特定のモードにおいて何が使えるのか?を表しています。
※開発サイクルのステージは左から右へ進んでいきます。初期→→→後期
モード | 設計 | 開発 | ビルド | テスト/プレイ | 公開 |
---|---|---|---|---|---|
ファスト | 〇 | 〇 | × | エディタのみ | × |
バーチャル | 〇 | 〇 | アセットバンドルレイアウト | エディタのみ | × |
パックド | × | × | アセットバンドル | 〇 | 〇 |
どれだけのモードを同時進行できるか?は、開発チームの規模によって変わります。
中~大規模チームの場合は、全て同時進行で開発が進みます。
まだ実装していない機能の仕様書を作り(設計)、実装し(開発)、ビルドし、本番用のアプリをローカルにデプロイし(公開)、そのアプリで動作確認(テスト/プレイ)するというサイクルを毎日繰り返します。
そのようなチームの場合、常に3つのモードを用意する必要があるかも知れません。
デフォルトでは、アドレッサブルアセットはワーニングとエラーだけをログとして出力しますが、もっと詳しいログを出力することもできます。プレイヤー設定ウィンドウ(Edit > Project Settings > Player)を開き、その他の設定>設定セクションへ行き、スクリプト定義シンボルの入力欄に ADDRESSABLES_LOG_ALL を追加します。
AddressableAssetSettings オブジェクトのインスペクターにある Log Runtime Exceptions(実行時の例外)のチェックを外すことで、例外を無効にすることもできます。必要に応じて独自の例外ハンドラを使い、ResourceManager.ExceptionHandler プロパティーを実装することができます。ただし、アドレッサブルが実行直後の初期化を終えたあとに行うべきです(下記参照)。
ゲーム実行時にアドレッサブルアセットの設定にオブジェクトを割り当て、初期化処理を行わせることができます。CacheInitializationSettings オブジェクトは実行時に Unity のキャッシングAPIを制御します。初期化を行うオブジェクトを作成するには、IObjectInitializationDataProvider interface を継承する ScriptableObject を作成します。これは、実行時のデータと一緒にシリアライズする ObjectInitializationData の作成を行うシステムのエディターコンポーネントです。
Unity はゲームに2つのカテゴリーを構築することを推奨します。
- アップデートを必要としない変わることのないコンテンツ(静的コンテンツ)
- アップデートを必要とする常に変わり続けるコンテンツ(動的コンテンツ)
静的コンテンツはアプリで(またはインストール直後のダウンロードで)販売し、いくつかの大きなバンドル(データの塊)の中に含まれます。動的コンテンツはオンラインで提供されます。各アップデートに必要なデータ量を最小限に抑えるため、小さいバンドルにするのが理想的です。AASの目標のひとつは、簡単な作業でこれらの構築ができ、スクリプトを変更することなくデータの更新が行えることです。
とはいえ、新しいアプリのビルド全てを公開したくないとき、AASは静的コンテンツに変更することもできます。
アドレッサブルは各アセットのアドレスを記録するため、また、どこに、どのようにアセットをロードするのかを指定するためにコンテンツカタログを使用します。記録を更新する機能を使ってアプリを提供するため、このカタログのオンラインコピーを元のアプリに通知しなければいけません。その準備には、AddressableAssetSettings(アドレッサブル・アセットの設定)インスペクターにある、Build Remote Catalog setting(ビルド・リモート・カタログの設定)を有効にします。これによって、指定されたパスからのロードと、指定されたパスにカタログのコピーをビルドすることが保証されます。このパスはアプリ公開後は変更できません。コンテンツを更新するには、前回指定したパスにファイルを上書きするために、新しいバージョンのカタログ(同じファイル名)を作成します。
アプリケーションのビルドによって、ユニークな(一意な)アプリ・コンテンツのバージョンを表す文字が生成されます。それを使って、各アプリはロードするべきコンテンツカタログを識別します。サーバーには、コンフリクト(競合/衝突/重複)を起こすことなくアプリの複数のバージョンのカタログを含めることができます。必要なデータは addressables_content_state.bin ファイルに保存されます。このファイルにはバージョンを表す文字と、各アセットのハッシュ情報と一緒にStaticContent(静的コンテンツ)としてマークされたグループに含まれます。初期設定では、このファイルは AddressableAssetSettings.asset ファイルとして同じフォルダに配置されます。
addressables_content_state.bin ファイルは、AASの静的コンテンツのアセットグループで使う依存関係の情報とハッシュ値が保存されています。StreamingAssets フォルダにビルドした全てのグループは、静的コンテンツにマークされるべきですが、巨大なリモートグループ(どこかのネットワーク上に存在するグループ)も、この指定による利益を得られることがあります。次のステップ(コンテンツをアップデートする準備、詳細は下記参照)で、静的コンテンツのいずれかのグループが変更されたアセットを含んでいるか、アセットをどこか別の場所へ移動した場合に、このハッシュ値を決定します。
もし、いずれかの静的コンテンツグループ内に変更のあったアセットがある場合、Prepare For Content Update(コンテンツをアップデートする準備)コマンドを実行する必要があります。静的グループ以外で変更のあったアセットを特定し、それらを新しいグループへと移動します。
以下の方法で新しいアセットグループを作成できます。
- UnityエディタのAddressables Window(アドレッサブルズ・ウィンドウ)(Window > Asset Management > Addressable Assets)を開く。
- アドレッサブルズ・ウィンドウで、上部にあるメニューバーのBuild(ビルド)を選択してから、Prepare For Content Update(コンテンツのアップデート準備)を選択する。
- ビルドデータファイルのダイアログが開くので、addressables_content_state.bin ファイルを選択(初期設定では、プロジェクトフォルダ内の Assets/AddressableAssetsData にある)
このデータは、アプリを最後にビルドしてから更新されたアセットや依存関係を決定するために使われます。AASはこれらのアセットを準備中の新しいグループに移動します。
注意:このコマンドは全ての変更点が非静的グループ(non-static groups)(非静的グループ=動的グループ)に限定される場合、何も行いません。
重要:Prepare For Content Updateを実行する前に、バージョン管理システムでブランチを作ることをお勧めします。この命令は、アセットグループ内の更新中のコンテンツを適切な方法で配置し直します。ブランチを作ることによって、次の新しいアプリのリリースを確実なものにし、準備を進めているコンテンツの巻き戻しを可能にします。
以下の手順で行います。
- Unity エディタでアドレッサブルズ・ウィンドウ(Addressables window)を開く(Window > Asset Management > Addressable Assets)。
- アドレッサブルズ・ウィンドウの上部にあるメニューでビルド(Build)を選択し、コンテンツをアップデートするためのビルドを行う。
- ビルドデータファイル(Build Data File)のダイアログが開くので、アプリのビルド用ファイルが存在しているビルド用フォルダを選択。
ビルド用フォルダ内に addressables_content_state.bin ファイルがなければビルドできません。
ビルドすることによって、コンテンツカタログ、ハッシュファイル、アセットバンドルが生成されます。
生成されたコンテンツカタログは選択しているアプリのビルド内にあるカタログと同じ名前を持ち、古いカタログとハッシュファイルを上書きしています。アプリはハッシュファイルをロードし、新しいカタログが有効かどうかを判断します。AASはアプリがリリースしたか、既にダウンロードした存在するバンドルから更新されていないアセットをロードします。
AASは、アセットバンドルを生成するためにコンテンツのバージョンを表す文字列と、設置場所の情報を addressables_content_state.bin ファイルから取得して使用します。更新されたコンテンツを含まないアセットバンドルは、更新するために選択したビルド内にあるものと同じファイル名で書き込まれます。アセットバンドルが更新されたコンテンツを含む場合、元のアセットバンドルと共存できるように、更新されたコンテンツを含む新しいアセットバンドルが新しいファイル名で生成されます。新しいファイル名が使われているアセットバンドルだけを、コンテンツを配信する場所にコピーする必要があります。
AASは静的コンテンツ用のアセットバンドルもビルドしますが、アドレッサブル・アセットに設定されたデータは静的コンテンツ用のアセットバンドルを参照しないので、コンテンツを配信する場所にアップロードする必要はありません。
この例では、公開したアプリは以下のグループ構成になっているものとします。
Local_Static 静的ローカル |
Remote_Static 静的リモート |
Remote_NonStatic 動的リモート |
---|---|---|
アセットA | アセットL | アセットX |
アセットB | アセットM | アセットY |
アセットC | アセットN | アセットZ |
各グループにあるアセット(アセットA, アセットL, アセットX)をひとつずつ変更した場合、Prepare For Content Update(コンテンツのアップデート準備)を実行することによって、ローカルのアドレッサブルの設定は以下のようになります。
Local_Static 静的ローカル |
Remote_Static 静的リモート |
Remote_NonStatic 動的リモート |
content_update_group コンテンツ・アップデート・グループ(動的) |
---|---|---|---|
アセットX | アセットA | ||
アセットB | アセットM | アセットY | アセットL |
アセットC | アセットN | アセットZ |
Prepare For Content Update(コンテンツのアップデート準備)は、実際には静的グループの編集を行うため、あまり直感的ではない点に注意してください。AASは上記のレイアウトのビルドを行いますが、静的グループはビルドの成果物から破棄されます。そのため、プレイヤー視点で見ると以下のようになります。
Local_Static 静的ローカル |
---|
アセットA |
アセットB |
アセットC |
静的ローカルバンドルは既にプレイヤーのデバイスにあるので、それを変更することはできません。これは古いバージョンの アセットA はもう参照できないということです。その代わり、死んだデータとして、プレイヤーのデバイス上に存在しています。
Remote_Static 静的リモート |
---|
アセットL |
アセットM |
アセットN |
静的リモートバンドルは変更できません。プレイヤーのデバイス上に既に存在していない場合、アセットM か アセットN のダウンロード要求があったとき、同時にダウンロードされます。アセットA のように、この古いバージョンの アセットL は参照できなくなっています。
Remote_NonStatic (old) 静的リモート(古い) |
---|
アセットX |
アセットY |
アセットZ |
この時点で、動的リモートバンドルは内容が古くなっています。サーバーから削除することは可能ですが、いずれにしても現時点ではダウンロードされません。ローカルにキャッシュされていたとしても、最終的にはキャッシュから削除されます。アセットA や アセットL のように、この古いバージョンの アセットX はもう参照できません。
Remote_NonStatic (new) 静的リモート(新しい) |
---|
アセットX |
アセットY |
アセットZ |
古い動的リモートバンドルは、ハッシュファイルによって区別される新しいバージョンに置き換えられます。アセットX のバージョン更新によって新しいバンドルに更新されます。
content_update_group コンテンツ・アップデート・グループ |
---|
アセットA |
アセットL |
コンテンツ・アップデート・グループバンドルは、修正を行うアセットで構成されます。
この例に含まれる内容は以下
- 変更したローカルのアセットは使われないままユーザーのデバイスに永久に残る。
- ユーザーが既に非静的なバンドルをキャッシュしている場合、変更していないアセットを含むバンドル(今回の例では、アセットYやアセットZ)を再ダウンロードする必要がある。ユーザーがバンドルをキャッシュしていない場合は、動的リモートバンドルをダウンロードするだけで済ませるのが理想。
- ユーザーが既に静的リモートバンドルをキャッシュしている場合、変更したアセット(今回の例では、コンテンツ・アップデート・グループ経由でアセットL)をダウンロードするだけで済ませることが理想。ユーザーがバンドルをキャッシュしていない場合、コンテンツ・アップデート・グループ経由で新しいアセットLをダウンロードするか、静的リモートバンドル経由で無効になったアセットLの両方をダウンロードしなければいけない。キャッシュが初期状態かどうかに関わらず、いずれかの時点で、ユーザーは既に機能しなくなったアセットLをデバイス上に持つことになり、決してアクセスされることのないデータを永久にキャッシュすることになる。
リモート・コンテンツにとっての最適な設定は、ケース・バイ・ケースになるため、状況に合わせて、その都度、調節していく必要があります。
「【Unity】Addressable Asset System 公式マニュアルの和訳 Part4」への1件のフィードバック