Richard Fabian のData Oriented Designでは、オブジェクトが持つことができるさまざまなプロパティが個別の配列に分割され、これらの配列内のデータを処理することによって機能が作成される、ゲーム用のコンポーネント ベースのオブジェクトの例を示しています。彼はレンダリングの例を挙げています:
struct Orientation { vec pos, up, forward, right; };
SparseArray<Orientation> orientationArray;
SparseArray<Vec> velocityArray;
SparseArray<bool> isVisible;
SparseArray<AssetID> modelArray;
void RenderUpdate() {
foreach( {index, assetID} in modelArray) {
if( index in isVisible ) {
gRenderer.AddModel( assetID, orientationArray[ index ] );
}
}
}
私が混乱しているのは、このコードがキャッシュフレンドリーであるということです。私が理解していることから、データ指向設計は、特定の操作に必要な関連データを連続したメモリに保持することでパフォーマンスを向上させるため、データを反復処理して更新すると、キャッシュミスの数が減ります。ただし、この例では、レンダリングには 3 つの異なる「コンポーネント」からの情報が必要であるため、反復ごとに異なるデータ配列にアクセスすることになります。また、コンポーネントがそれぞれと対話する必要がある場合に ID を検索する必要があるため、パフォーマンスが低下する可能性があることは言うまでもありません。他人のデータ。
データ指向設計を実践するために、非常に単純な 2D ゲームに取り組んでいます。上記のパターンに従ってオブジェクトを移動させるなど、ゲームの基本的な動作をモデル化するとしたら、次のようになります。
struct Position { int x, y; };
struct Velocity { int x, y; };
SparseArray<Position> positionsArray;
SparseArray<Velocity> velocitiesArray;
次に、物理の更新で、対応するinで各Position
inを更新します。positionsArray
Velocity
velocitiesArray
キャッシュがこの操作に必要なデータを単一の構造体に結合する方がよいのではないでしょうか:
struct MoveComponent { Position pos; Velocity vel };
SparseArray<MoveComponent> moveComponents;
位置を更新するために必要なデータがすべて連続して保存されていますか?