UDN
Search public documentation:
ContentStreamingJP
English Translation
中国翻译
한국어
Interested in the Unreal Engine?
Visit the Unreal Technology site.
Looking for jobs and company info?
Check out the Epic games site.
Questions about support via UDN?
Contact the UDN Staff
中国翻译
한국어
Interested in the Unreal Engine?
Visit the Unreal Technology site.
Looking for jobs and company info?
Check out the Epic games site.
Questions about support via UDN?
Contact the UDN Staff
コンテンツ ストリーミング
ドキュメントの概要:コンテンツのストリーミングおよびシームレスなワールドの計画と実装について説明概要
次世代のコンソールプラットフォームは、グラフィックと計算パワーの飛躍的な向上を約束します。しかしそれらのプラットフォームでは、大きな記憶容量が求められます。次世代ゲームが最大限の詳細さを達成するために、ストリーミングとシームレス ワールド サポートを使用してゲーム コンテンツをオンデマンドでロードすることが必要になります。ストリーミング
ここでは、「ストリーミング」を次のような意味で使用します。視覚予測方式に従ってサイズの大きい生コンテンツをオンデマンドで(通常は数メガバイト)最適化して読み込み、同時に、高速データ変換が必要ないように、プラットフォームのネイティブ形式で直接メモリにロードすることです。 ストリーミングシステムは、UObject 派生クラスのような複合オブジェクト指向データをサポートすることを目指していません。レベルの UTexture オブジェクト (テクスチャを記述している200バイトの UObject 派生クラス) は、レベルのロード元であるメモリ内に常駐していますが、そのテクスチャに関連づけられたバルク ミップマップデータをストリーミングできます。言い換えると、ストリーミング サポートは、バルク コンテンツのみを対象としており、複合データ構造を対象にしていません。 ここでは、テクスチャミップマップのストリーミングと、他のストリーミングが必要なコンテンツ用のパッケージ ストリーミングの使用のみを対象としています。オーディオをストリーム予定はありません。シームレス ワールド
Unreal Engine 3 はシームレス ワールドをサポートしています。シームレス ワールド システムは、レベルに関連づけられた複合オブジェクト指向データをバックグラウンドで動的にロード/アンロードするために使用されます。このシステムをストリーミングと組み合わせることで、ワールドに関連づけられたすべてのデータを動的にロードすることができます。 Unreal Engine 3 のワールド (UWorld オブジェクト) は複数のレベル (ULevel オブジェクト) で構成できます。; 典型的なゲームには、数百もの個別のレベルが含まれています。これらのレベルは、近接性、明示的なロード/アンロード トリガ、その他の基準に基づいて動的にロードおよびアンロードすることができます。 レベルでは、個別にロードおよびアンロードできるアクタの集まりやその他の複合オブジェクト指向データの組み合わせを定義します。概念的に、あるレベルが参照するすべてのオブジェクトがロードされ、C++ とスクリプトコードが参照することができる場合 (すなわち FindObject?) と、まったくできない場合のいずれかに分かれます。この atomicity (アトミシティ) によって、レベルによって参照されるオブジェクトに、その他の任意のオブジェクトへのポインタを含めることができます。これは、アクタ、コンポネント、マテリアル、ゲームプレー スクリプトの複合階層において非常に頻繁に起きるパターンです。このため、C++ とスクリプト コードは、まだローディングを終えていないオブジェクトへの参照を処理する必要は全くありません。 ローディングやその他の原子的ファイル別操作をサポートする ULevel 抽象化もありますが、一般にゲームプレーコードからは隠されています。アクタとゲームプレー機能は UWorld 抽象化を通して表示され、現在ロードされている静的および動的アクタのすべてを 1 つのリストに集積します。これにより、普通のゲームプレーコードは、レベル「境界」を考慮する必要がなく、アクタはワールド内を移動しても「レベル変更」しません。非同期パッケージ ローディング
シームレスなワールド ローディング コードは、バックグラウンドでパッケージを完全にロードできる機能に基づいています。このコードを使用することで、他のデータの任意の組み合わせを (プレ) ロードし、もう一度ガーベジコレクションに削除させることができます。詳細な説明
パッケージ ローディング
Unreal のローディング コードのコアは複数のパッケージで構成されており、その依存関係は DLL をモデルに作られています。パッケージには、以下の内容が、この順序で必ず含まれています。- パッケージ ファイル サマリ
- 名前テーブル
- インポート テーブル
- エクスポート テーブル
- UObject::LoadPackage が BeginLoad を呼び出す
- UObject::GetPackageLinker が呼び出され、
- そのパッケージについて既存のリンカーがあるかどうかをチェック
- 完全に記述されていないファイル名があればそれを解決
- 「真の」ファイル名を使用して ULinkerLoad オブジェクトを作成
- 返された ULinkerLoad は、順番に「すべてのオブジェクトをロード」/「すべてのエクスポートを作成」に使用されます
- EndLoad が呼び出され、
- ループ内で実際のシリアライゼーションと PostLoad 呼び出しを宛先指定します
- ダングリングポインタを避けるために、キャッシュされたインポートオブジェクトをインポートテーブルから切り離します。
- ダングリングポインタを避けるために、エクスポートテーブルから強制エクスポートを切り離します
- パッケージファイル概要が読み込まれる
- 名称テーブルが読み込まれる
- インポートテーブルが読み込まれる
- エクスポートテーブルが読み込まれる
- 既存のオブジェクトは潜在的にエディタ内のエクスポートテーブルに組み込まれる。
- すべてのインポートが確認される (対応するソースリンクで示されたエクスポートと一致)。
非同期パッケージ ローディング
エンジンは、非同期方法でのパッケージ ローディングをサポートします。より正確には、エンジンは渡されたリンカー内のすべてオブジェクトの、非同期方法によるロードをサポートします。この機能は UObject::PreloadLinkerAsync にあり、下記を行います。- 適切なリンカー上で ULinkerLoad:CreateExport にマップする ULinkerLoad:CreateImport を経由して、すべてのインポートを作成します
- すべてのエクスポートオブジェクトを作成して、それらのデータを (1 つ 1 つ) シリアライズします
- PreLoad (実際のシリアライゼーション) がすべてのエクスポートに経路指定済みであることを確認します
- PostLoad をオブジェクトに宛先指定します
シークフリーアスペクト
シークフリー ローディングの場合、すべてのインポートがすでにロード済であることが保証されます。そのため、インポート作成段階にディスク動作が発生しません。パッケージをロードするために必要なすべてのオブジェクトは、たとえそれらがパッケージの一部でなくても、エクスポートテーブルに入っています。これは、RF_ForceTagExp と呼ばれるオブジェクトフラグによって達成されます。このフラグは、インポートテーブル内にしか常駐できないオブジェクトを、保存時に、パッケージにシリアライズすることを強制するため、それ以降はオブジェクトがエクスポートテーブルに属することになります。これらのオブジェクトは特別にフラグされます。これによって、エクスポートが作成されるときには、オリジナル パッケージからロードされたかのように作成されます。つまり、ロードされたパッケージではない「アウターモスト (最外)」を持つことになります。 エンジンは、「強制エクスポート」用のエクスポートを作成する前に、オブジェクトがすでにメモリ内に存在しているかどうかをチェックし、それを reconcile (調和) します。これにより、複数のレベルの数個のマップが、一度ロードするだけでよい同じコンテンツを共有できます。 非同期ローディングについて注意すべきなのは、非同期バックグラウンドローディングの実行中は通常のローディングが発生できないことです。このため、非同期ロード要求がある場合、それが完了するまであらゆるバックグラウンド アクティビティが遮断されます。ガーベージコレクションについてもこのことが当てはまります。ガーベージコレクションは非同期ローディングの間は発生できないため、非同期ローディングが完了するまで、その動作をブロックし、完了後に作業を実行します。自動時限式のガーベジコレクションコードは、ロードをブロックする結果が生じるのを避けるため、未処理の要求がある間はガーベジコレクタの呼び出しを回避します。 シークフリー ローディングは、解決時 (インポート作成時として知られる) に、シークが発生することを避けるため、パッケージに既にロードされていることが保証されていない依存関係を複製する方法に依存しています。大多数のシークは、UMaterialExpression などの小さいヘルパーオブジェクトによって引き起こされます。これは、事実上まったくペイロードがなく、複製する負荷が非常に小さいオブジェクトです。一方静的メッシュデータは、サイズの点から見て、通常複製されるデータのうちでもおそらく最も負荷の高いものでしょう。 通常テクスチャは、そのペイロード/バルクデータを複製しませんが、UObject データと最低ミップレベルだけをシークフリー パッケージに入れ、残りをテクスチャ ストリーミング コードを経由してストリーミングさせます。 シークフリー ローディングをほとんど犠牲にすることなく、複製を削減することもできます。これを行うには、共有コンテンツを持つパッケージを作成して、最初にそれらをロードします。この大部分は、手動プロセスで行われます。そのため、このプロセスを余り活用することは現在のところ想定していません。ほとんどのマップで共有されていないデータを複製することで十分足りると考えているためです。 これはほとんどが手動での処理で、マルチプレイヤーマップ用オーディオを除き、 Gears of War 用には作成していません。ネットワーキング
ネットワーキング コードは、インデックスを経由してオブジェクト参照を伝えるために使用されるパッケージ マップと呼ばれる構造に依存しています。パッケージ マップ コードは、オブジェクト リンカー インデックスとトップレベル パッケージ名を使用して、オブジェクトをインデックスに、またはその逆に変換します。シークフリー ローディング コードを通してロードされたオブジェクトには、関連づけられたリンカーがありません。そのため、コードは元のリンカー インデックスをシークフリー パッケージに保存し、そのパッケージを使用してパッケージ マップをビルドする必要があります。初期ローディング
初期ローディングには、少し手間がかかります。クッキング ステップの間には次が行われます:- 各スクリプト パッケージがロードされる
- パッケージよって参照されるすべてのコンテンツが、強制エクスポートによって、パッケージに入れられる