
チャンクの設定
チャンク とは単独でデプロイおよびダウンロードが可能なアセットのコレクション (ゲーム コンテンツ) のことです。プロジェクトには Chunk 0 と呼ばれるチャンクがデフォルトで 1 つ付いており、すべてのアセットはこのチャンクに含まれています。アンリアル エンジン 4 のステージング システムは、アセットをさまざまなチャンクに割り当てた後、各チャンクから独立した .pak ファイルを作成します。このファイルはゲームのターゲット プラットフォームに基づいて、プラットフォーム固有のデプロイメント システムへ統合することができます。Battle Breakers の場合、これらのファイルは HttpChunkInstaller プラグインを使ってダウンロードするファイルとなりました。以前はチャンクの作成にクッカーのコールバックを使用する方法がありましたが、4.17 以降は AssetManager が最速かつ最もフレキシブルな方法となっています。これらの機能を使用するには、パッケージ化に関するドキュメント の説明どおりにチャンクの作成設定をしておく必要があります。Battle Breakers (コード名『World Explorers』) は開発の開始から少し経過していたので、Asset Manager を使用するための変換が最初のステップでした。そのために、プライマリ アセットにするゲーム コンテンツの種類を調べて特定し、AssetManagerSettings に設定しました。Battle Breakers には 28 種類のプライマリ アセット タイプがありましたが、一番興味深かったコンテンツ要素はマップとキャラクターでした。Battle Breakers にはユニークなアートが付いたキャラクターが数百個ありますが、ほとんどのプレイヤーはこの一部にしかアクセスできません。またデザイナーは、プレイヤーの摩擦を避けるために、オンボーディング / チュートリアルのすべてのコンテンツの初回ダウンロードを希望しました。従って、Battle Breakers が必要とするチャンキング モデルのために次の 3 種類のチャンクを作りました。まずオンボーディング コンテンツ用に Chunk 0、プレイヤーがオンボーディングを完了した時にダウンロードされるその他のマップと共有ゲームプレイ コンテンツ用に手動で定義した数々のチャンク、そしてオンデマンドでダウンロード可能なその他のキャラクター用に自動的に生成されるチャンクです。次の例は DefaultGame.ini からの抜粋です:
[/Script/Engine.AssetManagerSettings] +PrimaryAssetTypesToScan=(PrimaryAssetType="Character",AssetBaseClass=/Script/WorldExplorers.WExpCharacterDefinition,bHasBlueprintClasses=False,bIsEditorOnly=False,Directories=((Path="/Game/Characters/Classes"), (Path="/Game/World/Map")),Rules=(Priority=1,CookRule=AlwaysCook)) +PrimaryAssetTypesToScan=(PrimaryAssetType="WExpChunkDefinition",AssetBaseClass=/Script/WorldExplorers.WExpChunkDefinition,bHasBlueprintClasses=False,bIsEditorOnly=False,Directories=((Path="/Game/Chunks")))手動でチャンク化を行うために、そのチャンクがオンボーディング用、自動ダウンロード用、オンデマンド ダウンロード可能なコンテンツ用のどれかを識別する UPrimaryAssetLabel の特別なサブクラスをUBattle Breakers 用に作成しました。各ラベルの Rules セクションの中には手動で定義された ChunkId と Priority があります。またラベルはアーティストとデザイナーによる修正が可能なエディタ コレクションを指定します (4.18 の新機能)。高優先度のプライマリ アセット / ラベルで管理されている場合を除き、コレクションのアセットはすべてこのチャンクに入ります。キャラクター用に自動生成されるチャンクを作成するために、各キャラクター上に SetPrimaryAssetRules を呼び出して Chunk 1000 からチャンクに割り当てていくコードを Battle Breakers 専用の UAssetManager のサブクラスに追加しました。これらのチャンクの割り当ては、時間が経過しても確実に一定を保つように単純な .csv ファイルに保存 / ロードされます。さらに、特定の Primary Asset ID の管理対象となっているアセットを判定するための仮想関数 ShouldSetManager の中に、ゲーム独自のハックも 2、3 個作る必要がありました。それぞれのゲームのニーズに合わせて、コンテンツをチャンクに割り当てる独自のルールが必要なのです。AssetManager は必要に応じてサブクラス化とカスタマイズを行ってこれに対応しています。

Battle Breakers には、チャンク間の親子関係を指定する ChunkDependencyInfo というツールも使用されています。このツールを設定するには、このような行を DefaultEngine.ini に追加します。
[/Script/UnrealEd.ChunkDependencyInfo] +DependencyArray=(ChunkID=100,ParentChunkID=11) +DependencyArray=(ChunkID=101,ParentChunkID=11)
これらの行はチャンク 100 とチャンク 101 がチャンク 11 の子であることを指定します。チャンク 11 に含まれているアセットはチャンク 100 またはチャンク 101 には含まれないということです。デフォルトではすべてのチャンクがチャンク 0 の子になっています。つまり初回起動チャンクが無駄に他のチャンクに複製されることはありません。チャンクの階層を正しく設定することによって、必要なディスク サイズをプレイヤーのデバイス上で最小化し、コンテンツの重複を防ぎました。
チャンクの割り当ての分析
チャンクの初期設定を行った後、結果が期待したどおりになっているかを確認したところ、期待通りになっていませんでした。そこで、これらの問題の原因究明を容易にするために、アセットの割り当て先チャンクと割り当て理由示す新しいトラック ツールを 4.19 に幾つか追加しました。1 つ目のツールは [Asset Audit] ウィンドウです。エディタの [Windows] --> [Developer Tools] --> [Asset Audit] からアクセスします。[Asset Audit] ウィンドウを開いて [Add Chunks] ボタンをクリックすると、ゲームに存在するすべてのチャンクのサマリーがウィンドウに表示されます。
チャンクを個別に調べるには、チャンクを右クリックし、[Size Map] または [Reference Viewer] のいずれかを選択します。すると中に含まれているものが表示されます。Size Map ではコンテンツが上位アセット (または Primary Asset ID) に応じてグループ化される包括的なビューが表示されます。一方、リファレンス ビューではフィルターとオプションを使って個々のアセット間の親子関係が表示されます。一例として、Chunk_7 のリファレンス ビューアを使って 85MB のコンテンツが割り当てられた理由が分かります。

この時点で Chunk_7 のリファレンス ビューから Chunk_Onboarding が参照の 1 つであることが分かったので、ダブルクリックしてリファレンス ビューアで詳しく見てみます。緑のボックスはプライマリ アセット、そしてグレーのボックスは実際にディスク上にあるアセットです。プライマリ アセットからディスク アセットへの参照は管理リファレンスと呼ばれます。ウィンドウの左上にある [Show Management References] オプションをオンにすると表示されます。このケースでは、これらが明示的な管理リファレンスであることが白い線で示されています。つまり、このケースでは上述したコレクションによってアセットはプライマリ アセットの一部として明示的に含まれることを意味します。[Search Breadth Limit] オプションをオフにして下にスクロールすると、暗示的な管理リファレンスを示すピンクの線が出てきます。これらは、明示的に管理されたアセットから再帰的に参照されたため、管理セットに自動的に追加されたアセットです。
チャンクの割り当てを調べる方法は他にもあります。コンテンツ ブラウザで調査対象のアセットを探して右クリックします。そしてリファレンス ビューアを選択し、手動で [Show Management References] をオンにします。すると、そのアセットを管理するプライマリ アセットが (ある場合は) 表示されます。

この例を見ると、アセットが WExpCharacterDisplay プライマリ アセットによって暗示的に管理されていることが分かります。プライマリ アセットをダブルクリックすると割り当て先は Chunk 1167 であることが分かります。これは左上にある Display アセットからのハード参照のためです。そのアセットをダブルクリックすると、プライマリ アセットで明示的に管理されていることが分かります。
さらに、コンテンツ ブラウザから選択する、または [Asset Audit] ウィンドウの大量追加オプションを使用して、複数のリアルなアセットを [Asset Audit] ウィンドウに追加する方法もあります。この例では、すべての Texture2D アセットを [Asset Audit] ウィンドウに追加し、サイズでソートしました。幾つかカラムもオフにして見やすくしました。

この例では、最大級のテクスチャのほとんどは Chunk 2 で発生しています。各テクスチャを右クリックしてリファレンス ビューアを見ると、テクスチャがそのチャンクに入っている理由を確認することができます。[Asset Audit] ウィンドウにも便利な情報があります。ここに表示されるメモリ サイズは ResourceSize からの推測です。また、Total Usage はそのテクスチャを参照するプライマリ アセットの数をプライマリ アセットの優先度でスケールしています。
Optimizing Disk Size
チャンクが期待どおりに設定されているかを分析ツールで確認したところ、大きすぎるチャンクがまだいくつかありました。これを修正するために、同じツールを使ってすべての空き領域を探しました。これらのツールと技術は実はゲームにチャンク処理を設定しない場合でも使うことができます。4.19 で大幅に改善されました。まずは、ディスク上で実際にクック処理されたサイズを調べるために [Asset Audit] ウィンドウのチャンク ビューに戻ります。上のスクリーンショットのように、このウィンドウはデフォルトでエディタのディスク サイズを表示します。サイズは実際にクックされたビルドのサイズとはまったく異なる場合があります。ただし、ビルドをローカルでクックする場合は、そのドロップダウンがコンテンツのクック先のプラットフォームで追加されるので、シップするゲームでデプロイする実際のサイズが表示されます。また、[Custom] を選択しても、特定の DevelopmentAssetRegistry.bin ファイルをハードドライブから取り込むことができます。取り込んだファイルをアーカイブするようにビルド プロセスが設定されていれば、そのファイルを使ってプロダクションビルドから実際のサイズの数字を取得できます。
使用するプラットフォームを右クリックし [Size Map] を選択すると、ディスク サイズの配分の全体像が表示されます。この例は、最適化する前の Battle Breakers の Chunk_0 です。

チャンク内のすべてのアセットがディスク上のサイズに合わせて拡大表示されます。色のついたボックスはそれぞれ別の上位レベルアセットまたは Primary Asset ID であることを表します。特定のアセット グループをもっとよく見るには、マウスホイールでズームインまたはダブルクリックします。前のビューに戻るには、ズームアウトまたは左上の矢印を使います。アセットを右クリックするとリファレンス ビューアまたは Asset Audit ビューのいずれかに切り変わり、詳細を調査することができます。Size Map ビューは、チャンクとプライマリ アセット管理リファレンスに関する情報を使って Size Map のコンテンツをフィルタ処理します。従って、実際にチャンクの中にあるアセットのみが表示されます。
Size Map アセットはサイズに基づいてスケールされるので、最適化すべき場所が迅速かつ明確に示されます。大きなブルーム テクスチャといくつかの VR 固有アセットはモバイル タイトルには必要ないので、ビルドから完全に削除しました。別のケースでは、チャンク間で特定のアセットを移動させるためにエディタ コレクションを修正しました。通常ディスク サイズはメモリと置き換えることができるので、これらと同じ技術はメモリの最適化にも使うことができます。実際は、特定のプラットフォームではランタイム中のメモリ使用量の計算をクック時に行うことはできません。従って、Size Map をメモリ サイズに切り替える場合は、リソース サイズに基づく精度の低い推測値を使用します。
これらのツールの使用とゲーム向けの最適化によって、ユーザーのダウンロードを高速化し、デザイナーによる変更の反映を可能にするチャンク設定を Battle Breakers に行うことができました。これらのツールは、すべてのゲームの整理と最適化に役立ちます。