記事ディレクトリ
アドレス指定可能な資産システム
1. 背景
Addressable システムの導入を開始する前に、まずいくつかの従来のリソース読み込み方法を確認しましょう。
- 直接参照: 直接参照の使用は最も簡単かつ高速ですが、動的にロードすることはできません。
- Resources リソース管理: リソースが使用されているかどうかに関係なく、Resources フォルダ内のすべてのファイルがインストール パッケージにパッケージ化されます。これにより、パッケージ本体が大きくなりすぎます。 ; リソースを加熱することはできません。リソースを更新します。リソースには、リソースをロードする際のリソース パスに関する厳しい要件があります。
- AssetBundle リソース管理: ホット アップデートは可能ですが、管理が困難です。
2. アドレッサブルシステムの概要
アドレス指定可能なアセット システムは、Unity によって開始された新しいリソース管理プラグインです。 Addressable システムは、Asset Bundle に基づいており、非同期読み込み、依存関係管理、メモリ管理などの豊富なリソース管理機能を提供し、開発者がリモート リソース更新をより簡単に実装できるようにします。
3. アドレッサブルシステムの利点:
- 迅速な反復:
開発の初期段階で急速開発段階に入るには、Addressable を使用します。好みのリソース管理テクノロジに関係なく、Addressable システムにすぐに切り替えることができます。コードを変更する必要はほとんどありません。 - 依存関係の管理:
システムは、要求されたコンテンツだけでなく、そのすべての依存関係も返すため、コンテンツを返す前にすべてのメッシュ、シェーダー、アニメーションなどがロードされます。 - メモリ管理:
Addressable は、リソースをロードするだけでなく、リソースをアンロードすることもできます。 - コンテンツのパッケージ化:
Addressable システムはすべての複雑な依存関係の接続を自動的に管理するため、リソースが移動または名前変更された場合でも、システムはパッケージ化するための正確な依存関係を効率的に見つけることができます。パッケージ化されたリソースをローカルからサーバーに移動する必要がある場合、Addressable システムを使用すると簡単にそれを実行できます。従来のアセット読み込み方法 (リソース/アセットバンドル) と比較して、Addressable システムには完全なビジュアル編集ウィンドウとメモリ管理が備わっています。
4. Addressable システムと AssetBundle の違い
- Addressable システムは、任意の場所からアセットをロードするためにアセットのアドレスのみを必要としますが、AssetBundle は指定されたバンドル パッケージからリソースをロードする必要があります。
- Addressable システムは参照カウントを使用してメモリのアンロードを自動的に管理しますが、AssetBundle では開発者が手動で管理する必要があります。
- Addressable システムは依存関係を自動的に管理しますが、AssetBundle では開発者が依存関係を自分で管理する必要があるため、維持がより困難になります。
- デフォルトでは、アドレス指定可能なリソース システムのすべてのロード操作は非同期操作であり、イベント リスナーを追加できますが、AssetBundle には同期ロードと非同期ロードがあります。
アドレッサブルシステムの使用
1. インストール
Unity 2018.2 以降の場合は、PackageManager を使用して Addressables をインストールします。
2. アドレス指定可能管理画面
ウィンドウ > 資産管理 > アドレス指定可能 > グループ ユーザー インターフェースを入力します
アドレス指定可能な設定:
リソースは組み込みデータとローカル グループに分割されますデフォルト (デフォルト) では 2 つのグループがあり、前者にはいくつかの組み込みリソースが含まれているため変更できません。後者はリソースを追加または削除できます。
- 作成: 新しいリソース グループを作成します。[Addressables Group] ウィンドウで [新しいグループの作成] > [パックされたアセット] を右クリックして、新しいリソース グループを作成することもできます。
- プロファイル: プロファイルの役割は主に、プロジェクトで使用する必要があるいくつかのアドレスを指定することです。このウィンドウで [作成] > [プロファイル] をクリックしてプロファイルを作成できます。各プロファイルには 4 つのデフォルト変数が含まれています。「作成」->「変数」をクリックして変数を展開することもできます。
- 道具:
- プロファイル: は、Addressable 全体の範囲を設定するために使用されます (4 つのパスの特定の値を構成します)。その後、ビルドのパス タイプを選択できます。プロファイルに基づく各グループの負荷 [OK] を選択します。
- ラベル: ラベルの追加と削除 ラベル。
- 分析: 分析は、プロジェクトのアドレス可能なレイアウトに関する情報を収集するツールです。場合によっては、Analyze はプロジェクトのステータスをクリーンアップするために適切なアクションを実行することがあります。他の場合には、Analyze はアドレス指定可能なレイアウトについてより多くの情報に基づいた決定を下すことを可能にする純粋な情報ツールです。
- ホスティング サービス: Addressables システムに付属するリソース サービス。リモート リソースを保存するディレクトリを指定し、サーバーに接続してリソースを更新できます。
- イベント ビューア: はモニタリングとデバッグに使用できます。前提として、「システム設定の検査」ウィンドウで「メッセージの送信」にチェックを入れる必要があります (パフォーマンスを消費するため、デフォルトではオフになっています)。
Addressables イベント ビューアを使用して、Addressables システムによって操作されるすべてのリソースの参照カウントを監視します。 Unity で、[ウィンドウ] > [アセット管理] > [イベント ビューア] を選択します。
イベント ビューアは参照カウントのみを考慮し、メモリ消費量は考慮しないことに注意してください。 [アセット] 列の下にリストされている各フレームで、各リソースの次の情報を確認できます:
FPS: 1 秒あたりのフレーム数。
MonoHeap: 使用されているメモリの合計量。
イベント数: フレームごとのイベントの合計数。
左右の矢印をクリックしてフレームごとに観察するか、「現在」をクリックして最新のフレームにジャンプします。 + ボタンを押して行を展開すると、詳細が表示されます。
イベント ビューアに表示される情報は、プレイ モード スクリプトで選択されたゲーム モードに関連しています。 イベント ビューアを使用する場合は、アセット間の依存関係が考慮されないため、[アセット データベースを使用] モードの使用を避けてください。 [グループのシミュレート] モードまたは [既存のビルド モードを使用] を使用しますが、後者の方がリソースの参照カウントをより正確に監視できるため、イベント ビューアに適しています。 - コンテンツの更新制限を確認する: 静的リソース グループを更新します。
- プレイモードスクリプト:
- アセット データベースを使用する (最速): ゲームプレイ中にゲームをすばやく実行できます。アセット データベースを通じてアセットを直接ロードするため、アナライザーやアセットバンドルの作成を必要とせずに高速な反復が可能になります。
- グループのシミュレーション(上級): アセットバンドルを作成せずに、レイアウトと依存関係のコンテンツを分析します。アセットは、パッケージ経由でロードされているように見せかけて、ResourceManager 経由でassetDataBase からロードされます。ゲーム中にバンドルがいつロードまたはアンロードされるかを確認するには、Addressables イベント ビューア ウィンドウで [ツール] > [イベント ビューア] を選択します。
- Exiting Build を使用する (ビルドされたグループが必要): はデプロイされたアプリケーションのビルドに最も近いですが、別の手順としてデータをビルドする必要があります。アセットが変更されていない場合、再生モードに入るときにデータを処理しないため、このモードが最も高速になります。このモードのコンテンツは、[ビルド] > [新規ビルド] > [デフォルトのビルド スクリプト] を選択するか、ゲーム スクリプトで AddressableAssetSettings.BuildPlayerContent() メソッドを使用して、Addressables グループ ウィンドウ ([ウィンドウ] > [資産管理] > [アドレス可能] > [グループ] > [グループ]) でビルドする必要があります。
- 建てる:
- 新しいビルド: すべてのリソースの準備ができたら、これをクリックしてパッケージ化します。
- 以前のビルドを更新する: リソースが更新されたら、これをクリックしてリソース パッケージを更新します。
- ビルドのクリア: ビルドされたリソースをクリアします。ゲームを再度実行するには、ゲームを再度ビルドする必要があります。
3. AddressableAssetSettings システム設定
Addressable システムの基本構成:
- 起動時のカタログ更新を無効にする: デフォルトではチェックされていません。チェックされていない場合、AA システムが初期化されるたびにカタログ ファイルが自動的に更新されます。これがチェックされている場合、カタログ ファイルは自動的に更新されません。これは、リソースが自動的に更新されないことを意味します。AA システムの初期化は、インターフェイスが初めて呼び出されたときに初期化されるか、Addressables をアクティブに呼び出すことができます。 InitializeAsync() を使用して初期化します。
- リモート カタログの構築: デフォルトではチェックされていません。チェックされている場合のみ、指定されたディレクトリにカタログが作成されます。今後、クライアントはこれをダウンロードできるようになります。比較および更新用のカタログ。
- ビルド パス: パッケージ化後にリソースが保存されるアドレス。
- Load Path: 资源加载地址。
- プロファイラー イベントの送信: デバッグの場合、リソースの読み込み時にイベントを EventViewer に送信できます。このツールを使用してリソースの使用状況を表示できます
- ログ ランタイム例外: リソースのロード時に例外を出力します。オンになっているときにリソースのロード中に例外が発生した場合は、直接スローされます。オフの場合は、リソースをロードするときに返されたエラーを使用することもできます。ハンドルを使用して例外情報を取得することもできます。同時に、マクロ ADDRESSABLES_LOG_ALL をプロジェクトに追加して、より多くのログ情報を表示することもできます。
4. リソースグループの設定
- ビルド パス: パッケージ化後にリソースが保存されるアドレス。
- Load Path: 资源加载地址。
- 高度なオプション:
- アセット バンドルの圧縮: .bundle ファイルの現在の圧縮方法は、LZ4 圧縮と LZMA 圧縮をサポートしています。
- ビルドに含める: パッケージ化するかどうか。デフォルトではオンになっています。オンになっていない場合、現在のグループはパッケージ化されません。
- リクエスト タイムアウト: タイムアウトを超えた後に UnityWebRequest が中止を試みる秒数を設定します。 (リモート リソース バンドルにのみ適用されます)
- バンドル モード: バンドルのパッケージ化方法を制御します。 PackTogether はグループをリソース パッケージにパッケージ化し、Pack Separately は各リソースを 1 つのパッケージにパッケージ化し、Pack Together By Label はラベルの同じリソースを 1 つのリソース パッケージにパッケージ化します。
- コンテンツ更新制限:
- 更新制限:
- リリース後は変更できません: 静的グループはリリース後に変更できません。コンテンツ更新の制限を確認して新しいリソース グループを作成することによってのみ増分更新できます。
- リリース後に変更可能: 非静的グループはリリース後に変更でき、更新時に上書きされます。
- 更新制限:
5. リソースにマークを付ける
リソースをアドレス指定可能としてマークするには 2 つの方法があります。アドレス指定可能なリソース パッケージをインストールした後、プロパティ パネルでマークするか、管理ウィンドウの指定されたグループにドラッグすることができます。リソースの [プロパティ] ウィンドウで、 [アドレス] チェックボックスをクリックし、リソースの一意の識別子を設定します。
注: マークしたアセットが Resources フォルダーにある場合、Addressable システムはアセットを Resources フォルダーから移動するように求めるプロンプトを表示します。
6. リソースのパッケージ化
リソース グループを構成し、必要に応じて再生モード スクリプトを設定してから、[ビルド] > [新規ビルド] > [デフォルト ビルド スクリプト] を使用してパッケージ化してテストします。
ローカル リソースのパッケージ化パス: Library/com.unity.addressables/StreamingAssetsCopy/aa/Android/
リモート リソースのパッケージ化パス: ServerData/Android/
同時に、リモート ディレクトリに .hash ファイルと .json ファイルが生成されます。.hash ファイルにはハッシュのみが含まれますカタログ ファイルの値。顧客注文のカタログ更新を検出するために使用される場合、ハッシュ値はカタログ更新があるかどうかを判断するために比較されます。json ファイルには、各 Ab パッケージのハッシュ値とアドレスが含まれています。
[ビルドを使用] > 以前のビルドを更新する リソース パッケージを更新するときは、bin ファイル (例として Android 環境、Anroid/.bin) を選択する必要があります。この bin ファイルには、次のビルドとの違いが記録されます。すべての Ab パッケージ依存関係とグループ化情報、Addressable システムはこの bin ファイルを通じて依存関係を管理します。
7. リソースをロードする
AssetReference を使用してリソースをロードします。
[SerializeField] private AssetReference m_AssetReference;
private void Start() {
m_AssetReference.LoadAssetAsync<GameObject>();
}
Addressables を使用して単一のリソースをロードします。
private void OnResLoadAsset(string key)
{
Addressables.LoadAssetAsync<GameObject>(key).Completed += OnCompleteLoad;
}
private void OnCompleteLoad(AsyncOperationHandle<GameObject> asyncOperationHandle)
{
GameObject go = GameObject.Instantiate(asyncOperationHandle.Result);
}
private void OnResInstantiate(string key)
{
Addressables.InstantiateAsync(key);
}
複数のリソースをロードします。
private void OnResLoadAsset(string key,string lable)
{
Addressables.LoadAssetsAsync<Texture2D>(new List<object> {
key, lable }, null,
Addressables.MergeMode.Intersection).Completed += OnCompleteLoadAssets;
}
private void OnCompleteLoadAssets(AsyncOperationHandle<IList<Texture2D>> asyncOperationHandle)
{
//DebugTools.Log(asyncOperationHandle.Result.Count);
}
注: 3 番目のパラメータ MergeMode は、リソースのマージ モードを検索します。例として、受信パラメータを new List{key,label} とします。
- Node または UseFirst を使用する場合、最初のキーによってクエリされたリソースが取得されます。
- Union を使用する場合は、Union を取得します
- 交差点の場合、交差点を取得します
概要:
(1) リソースをロードするときに、ロードするリソースで指定されたタイプがリソース タイプと一致せず、Addressable システムがリソースを見つけられない場合、例外がスローされ、リソースをロードできません。前提条件: システム設定でプロファイラー イベントの送信がチェックされている必要があります。
(2) タグ管理を使用すると、同じリソースのアドレスとタグを同じにすることができます。同じタグを持つリソースが複数ある場合、Addressable システムは、条件を満たす最初のリソースを返します。条件。
(3) リソースのアドレス名が次のリソースのラベルと同じである場合、戻り値は依然として最初のリソースになります。Addressable システムは、リソースのアドレスとラベルを比較します。リソース。両方が異なる場合は続行されます。下方向に検索
8. リソースパッケージを更新する
ホット アップデートのリソース パッケージが変更された後、リソースを再パッケージする必要があります。
コンテンツの更新制限を確認する: 静的リソース グループの場合、これは更新制限です。プロパティの値は「リリース後は変更できません」です。クリックすると、以前にパッケージ化されたリソース グループによって生成された bin ファイルを選択するためのポップアップが表示されます。[変更を適用] をクリックして変更を適用します。追加または変更されたリソースは、新しいコンテンツ更新グループに移動されます。
以前のビルドの更新: 動的リソース グループが更新されるときに、この操作を実行するには、bin ファイルも選択する必要があります。これにより、システムが自動的に新しい AB パッケージを生成します。
9. ホットアップデートのコードと解決策
コアコード
public IEnumerator CheckForContentUpdate(List<object> keys)
{
for (int index = 0; index < keys.Count; index++)
{
AsyncOperationHandle<long> DownloadSize = Addressables.GetDownloadSizeAsync(keys[index]);
yield return DownloadSize;
if (DownloadSize.Result <= 0)
{
Debug.Log("[Addressable]:不需要更新的资源标签:" + keys[index]);
keys.Remove(keys[index]);
}
else
{
m_TotalSize += DownloadSize.Result / Mathf.Pow(1024, 2);
}
}
m_DownloadDependencies = Addressables.DownloadDependenciesAsync(keys, Addressables.MergeMode.Union, false);
yield return m_DownloadDependencies;
}
- オプション 1:
サーバーから更新されたリソース タグを取得します。
注: 動的リソースが更新されると、古いリソースは上書きされます。動的リソース グループには、更新する必要があるリソースがあります。ホット アップデート中に、リソース グループ全体がダウンロードされます。<リソースをグループに分割して、繰り返しのダウンロードとパッケージ化の粒度を減らすことが非常に重要です (複数のリソースには同じマテリアル、テクスチャなどが必要です)。
- オプション 2:
公式に提供されている Addressables.CheckForCatalogUpdates() メソッドを使用してカタログを確認し、更新する必要があるカタログを取得します。 - オプション 3:
すべてのキーを強制的に取得し、公式の Addressables.GetDownloadSizeAsync(Key) を使用してリソースを更新する必要があるかどうかを確認し、必要なすべての Key 値を取得します。更新される予定です。
リソース更新固有の実装:
公式に提供されている Addressables.GetDownloadSizeAsync(Key) メソッドを使用して、更新する必要があるすべてのリソース アドレスまたはタグ セットを取得します。 use Addressables.DownloadDependencyAsync (Key, Addressables.MergeMode.Union, false) 更新されたリソースをダウンロードします。
10. リソースの自動グループ化
プロジェクト内で管理する必要があるリソースが多すぎる場合、Addressable にチェックを入れたり、ドラッグ アンド ドロップする方法は明らかに適切ではないため、特定のフォルダー内のすべてのリソースをマークする方法を実装する必要があります。アドレス可能なリソースとして。
編集状態で新しいメニューを作成し、アセット ファイルを作成し、マークする必要があるリソース フォルダを設定します。複数のリソースを同時にマークできます。設定は次のとおりです:
public static void AutoSetGroup(string groupName, string lableName, string assetPath, bool isSimplied = false)
{
var set = AddressableAssetSettingsDefaultObject.Settings;
AddressableAssetGroup Group = set.FindGroup(groupName);
if (Group == null)
{
Group = set.CreateGroup(groupName, false, false, false, new List<AddressableAssetGroupSchema>
{
set.DefaultGroup.Schemas[0], set.DefaultGroup.Schemas[1]}, typeof(SchemaType));
}
string Guid = AssetDatabase.AssetPathToGUID(assetPath); //获取指定路径下资源的 GUID(全局唯一标识符)
AddressableAssetEntry asset = set.CreateOrMoveEntry(Guid, Group);
if (isSimplied)
{
asset.address = Path.GetFileNameWithoutExtension(assetPath);
}
else
{
asset.address = assetPath;
}
asset.SetLabel(lableName, true, true);
}
具体的なアイデア:
フォルダー パスに従って、フォルダー内のすべてのリソースのパス情報を取得し、グループ追加インターフェイスを呼び出し、現在のグループが存在するかどうかを確認し、存在しない場合は、 AddressableAssetGroup タイプのグループ オブジェクトを作成し、デフォルト状態を設定し、AssetDatabase.AssetPathToGUID を使用して現在のパス リソースの GUID を取得し、AddressableAssetSettingsDefaultObject.Settings.CreateOrMoveEntry() を通じて AddressableAssetEntry オブジェクトを作成します。Addressable がチェックされた後、リソース アドレスとラベルを設定します。
11. メモリ管理
リソースの読み込み
Addressables.LoadAssetAsync(); 単一のリソース
Addressables.LoadAssetsAsync(); 複数のリソース
Addressables.LoadSceneAsync(); シーンの読み込み
GamoeObject インスタンス化の読み込み
Addressables.InstantiateAsync(); インスタンス化の読み込み
GameObject.Instantiate( ); Unity はインスタンス化メソッドを提供します
リソースのアンロード
Addressables.UnloadSceneAsync(); シーンのアンロード
Addressables .Release(); releaseリソース、パラメータはリソースまたは AsyncOperationHandle ハンドル
Addressables.ReleaseInstance(); Addressable システムによって作成されたインスタンスを破棄します
注: Addressables.InstantiateAsync() と他の読み込み呼び出しのもう 1 つの違いは、オプションの trackHandle パラメーターがあることです。 false に設定すると、リソースは AsyncOperationHandle ハンドルを通じて解放される必要があり、リソースは AsyncOperationHandle.Result を通じて解放できなくなります。
参照カウントの問題: リソースのアンロード (手動と自動の両方)。
手動アンインストール、アドレス指定可能なシステムのロードおよびアンロード リソースはペアで存在します。Addrsssables.Release() または Addressables.ReleaseInstance() メソッドを使用してリソースをアンロードし、参照カウントを減らします。リソースの参照カウントが 0 に達すると、リソースはアンロードできる状態になり、すべての依存関係の参照カウントが減分されます。
自動的にアンインストールされ、それを含むシーンが閉じられたときに自動クリーンアップが可能になります。
アンインストールの問題
Addressables.ReleaseInstance() を使用して渡されたインスタンスが Addressables システム API によって作成されていない場合、またはインスタンスがハンドルを通じて作成された場合、システムはそれを検出し、メソッドが指定されたインスタンスを解放できないことを示す false を返します。この場合、インスタンスは破棄されません。
Addressables.LoadAsset() と Addressables.InstantiateAsync() の説明
Addressables.InstantiateAsync() には多少のオーバーヘッドが関連付けられているため、インスタンス化する必要がある場合は、フレームごと 同じオブジェクトを何百回もインスタンス化する場合は、Addressables.LoadAsset() メソッドを使用してオブジェクトをロードし、次に GameObject.Instantiate() を使用してインスタンス化することを検討してください。欠点は、Addressables システムが作成したインスタンスの数を認識しないため、適切に管理しないとメモリの問題が発生する可能性があることです。たとえば、誤ってロードまたはアンロードされたテクスチャを参照するプレハブは、レンダリングの問題 (またはさらに悪いこと) を引き起こす可能性があります。この種の問題は、メモリのアンロードがすぐにトリガーされない可能性があるため、追跡することが困難です。
メモリのクリア
リソースが参照されなくなっても、必ずしもリソース アセットがアンロードされたことを意味するわけではありません。一般的なアプリケーション シナリオには、リソース パッケージに含まれる複数のリソースが含まれます。例:
同じリソース パック (「スタッフ」) 内に 3 つのリソース (「木」、「戦車」、「牛」) があります。
「tree」がロードされると、「tree」の ref-count が +1 され、「thing」の ref-count が +1 されます。
その後、「tank」がロードされると、「tree」と「tank」の両方の ref-count が 1 になり、「stuff」パッケージの ref-count が 2 になります。
「ツリー」を解放すると、その ref-count は 0 になります。
この例では、「tree」リソースは実際にはアンロードされません。リソース パックまたはその一部をロードすることはできますが、リソース パックを部分的にアンロードすることはできません。パッケージ自体が完全にアンインストールされるまで、アセットはアンインストールされません。このルールの例外は Resources.UnloadUnusedAssets です。上記のシナリオでこのメソッドを実行すると、ツリーがアンロードされます。 Addressables システムはこれらのイベントを認識しないため、Addressables の参照カウントのみを反映します (メモリ内に存在するものを完全には反映しません)。 Resources.UnloadUnusedAssets の使用を選択した場合、これは非常に遅い操作となるため、ゲーム コンテンツが表示されない画面 (読み込み画面など) でのみ呼び出す必要があることに注意してください。
12. アドレス指定可能なパッケージングの粒度
Addressable システムを使用するときは、次のことを考慮する必要があります。 グループはいくつ必要か?このグループにはどのようなリソースが配置されていますか?梱包方法は「まとめて梱包」ですか、「ラベルごとにまとめて梱包」ですか、それとも「別々に梱包」ですか?明らかに、これは Assetbundle を使用するのと同じであり、開発者が自分で計画する必要があります。これは、Addressable が十分強力ではないためではなく、特定のプロジェクトに関連しており、各プロジェクトの状況が異なるためです。