3

ゲームループを編成するアイデアがあります。性能に疑問があります。物事を行うためのより良い方法があるかもしれません。

ゲーム コンポーネントの配列があるとします。それらはすべて、ゲームループの反復ごとに何らかの処理を行うために呼び出されます。例えば:

GameData data; // shared
app.registerComponent("AI", ComponentAI(data) );
app.registerComponent("Logic", ComponentGameLogic(data) );
app.registerComponent("2d", Component2d(data) );
app.registerComponent("Menu", ComponentMenu(data) )->setActive(false);
//...
while (ok)
{
//...
app.runAllComponents();
//...
}

利点:

  1. 優れたコンポーネントベースのアプリケーション、依存関係なし、優れたモジュール性
  2. コンポーネントを動的にアクティブ化/非アクティブ化、登録/登録解除できます
  3. 一部のコンポーネントは透過的に削除または置換でき、システムは何も起こらなかったため引き続き動作します (2 次元から 3 次元への変更) (チームワーク: すべてのプログラマーが独自のコンポーネントを作成し、コードをコンパイルするために他のコンポーネントを必要としません)

疑問:

  1. Component::run() への仮想呼び出しを含むゲーム ループの内部ループ
  2. Component::run() が bool 値を返し、この値を確認したいと思います。false が返された場合、コンポーネントを無効にする必要があります。したがって、内側のループはより高価になります。

さて、この解決策はどれほど良いでしょうか? 実際のプロジェクトで使用したことがありますか?

4

4 に答える 4

5

一部のC++プログラマーは、仮想関数のオーバーヘッドについてあまりにも多くの懸念を抱いています。仮想呼び出しのオーバーヘッドは、通常、関数が実行するものと比較してごくわずかです。ブールチェックもそれほど高価ではありません。

保守が最も簡単なコードになるような結果をすべて実行します。必要な場合にのみ、後で最適化してください。最適化する必要がある場合は、仮想呼び出しを排除することはおそらく必要な最適化ではありません。

于 2010-04-20T22:03:55.373 に答える
4

ほとんどの「実際の」ゲームでは、コンポーネント間の相互依存性についてかなり厳しい要件があり、順序が重要です。

これは影響する場合としない場合がありますが、シナリオなどに応じて、ユーザー操作の処理の前 (または後) に物理を有効にすることが重要な場合がよくあります。この状況では、正しく注文するために追加の処理が必要になる場合があります。

また、何らかの形式のシーン グラフまたは空間分割を使用する可能性が高いため、「コンポーネント」がそれを利用できることも確認する必要があります。これはおそらく、現在の説明を考えると、ツリーを何度も歩いていることを意味します. 繰り返しますが、これは設計上の決定によって回避できます。そうは言っても、一部のコンポーネントは空間パーティションの特定の部分にのみ関心がある場合があり、適切に設計する必要があります。

于 2010-04-20T22:05:32.287 に答える
1

モジュール式の合成オーディオ ファイル ジェネレーターでも同様のアプローチを使用しました。

100 の異なるモジュールをプログラミングした後、新しいモジュールをコーディングするときにパフォーマンスに影響があったことを思い出したようです。

全体としては、良いアプローチだと感じました。

于 2010-04-20T22:06:18.503 に答える
1

多分私はオールドスクールですが、一般的なコンポーネントの価値は実際にはわかりません。

struct GameObject
{
   Ai* ai;
   Transform* transform;
   Renderable* renderable;
   Collision* collision;
   Health* health;
};

これは、プレイヤーから敵、スカイボックス、トリガーまで、あらゆるものに有効です。指定されたオブジェクトで不要な「コンポーネント」をNULLのままにしてください。すべての AI をリストに入れたいですか? 次に、構築時にそれを行います。ポリモーフィズムを使用すると、そこにあらゆる種類の異なる動作をボルトで固定できます (たとえば、プレーヤーの「AI」がコントローラー入力を変換します)。これを超えて、すべての汎用基本クラスは必要ありません。とにかく、それは何をしますか?

「すべてを更新」では、各リストを明示的に呼び出す必要がありますが、入力の量は変わらず、移動するだけです。グローバル操作を必要とするセットのセットを難読化して設定する代わりに、操作が完了した時点で操作を必要とするセットを明示的に列挙します。

私見ですが、仮想通話が遅いわけではありません。それは、ゲーム エンティティの「コンポーネント」が同種ではないということです。それらはすべて非常に異なることを行うため、それらを異なる方法で扱うことは理にかなっています. 確かに、それらの間に重複はありません。したがって、別のものにキャストすることなく、その基本クラスへのポインターを意味のある方法で使用できない場合、基本クラスのポイントは何ですか?

于 2010-04-23T19:13:01.807 に答える