ゲームデザインでのフレームごとの関数呼び出しとイベント駆動型メッセージング


11

伝統的なゲームデザインは、私はそれを知っているように、使用する多型と仮想関数を更新ゲームオブジェクトの状態に。言い換えると、ゲーム内のすべてのオブジェクトで、同じ一連の仮想関数が定期的(例:フレームごと)に呼び出されます。

最近、もう1つ、ゲームオブジェクトの状態を更新するためのイベント駆動型メッセージングシステムがあることを発見しました。ここでは、オブジェクトは通常フレームごとに更新されません。代わりに、非常に効率的なイベントメッセージングシステムが構築され、ゲームオブジェクトは有効なイベントメッセージを受信した後にのみ更新されます。

イベント駆動型ゲームアーキテクチャについては、Mike McShaffryによる「Game Coding Complete」で詳しく説明されています。

以下の質問について、親切にお願いできますか?

  • 両方のアプローチの長所と短所は何ですか?
  • どちらが他より優れているのですか?
  • イベント駆動型ゲームデザインは、すべての分野で普遍的で優れていますか?したがって、モバイルプラットフォームでも使用することをお勧めしますか?
  • どちらがより効率的で、どちらが開発が難しいですか?

明確にするために、私の質問はゲームデザインから完全に多態性を取り除くことについてではありません。私は単に、イベント駆動型メッセージングと仮想関数への通常の(フレームごとの)呼び出しを使用してゲームの状態を更新することの違いとメリットを理解したいと思っています。


例: この質問はここで少し論争を引き起こしたので、例を挙げましょう。MVCによると、ゲームエンジンは3つの主要な部分に分かれています。

  1. アプリケーション層(ハードウェアおよびOS通信)
  2. ゲームロジック
  3. ゲームビュー

レーシングゲームでは、ゲームビューは画面をできるだけ速く、少なくとも30fpsでレンダリングする責任があります。ゲームビューもプレイヤーの入力をリッスンします。今これが起こります:

  • プレーヤーが燃料ペダルを80%まで押した
  • GameViewは「Car 2 Fuel Pedal Pressed to 80%」というメッセージを作成し、それをGame Logicに送信します。
  • Game Logicはメッセージを取得し、評価し、新しい車の位置と動作を計算し、GameView用に次のメッセージを作成します: "Draw Car 2 Fuel Pedal Pressed 80%"、 "Car 2 Sound Acceleration"、 "Car 2 Coordinates X、Y" .. 。
  • GameViewはメッセージを受信し、それに応じて処理します

どこで見つけましたか?いくつかのリンクまたは参照?私はこのアプローチを知りません(しかし、私は一般的にかなり奇妙なデザインパターンを知っています、そして私は一般的にオブジェクト指向の原則の適切な使用をアドバイスします)イベントベースの方が良いと思います。非同期呼び出しへのポーリング..計算と抽象化レベルで最適化されています
nkint

こんにちはNkint、コメントありがとうございます。基本的に、イベント駆動型通信と仮想関数の呼び出しを比較したいと思いました。質問を少し修正します。ところで、ゲームのデザインパターンが含まれているこのリンクを見てください:gameprogrammingpatterns.com
Bunkai.Satori

5
多分私はばかげていますが、多態性使用せずにメッセージングシステムをどのように機能させるのですか?イベントレシーバーインターフェイスを定義するには、なんらかの基本クラス(抽象またはその他)が必要ではありませんか?(編集:適切に反映された言語で作業していないことを想定しています。)
Tetrad

2
また、効率は実装の詳細に大きく関係します。「どちらが効率的か」は、現在の形で答えられる質問ではないと思います。
Tetrad、2011年

1
ゲームオブジェクトはティックする必要があります。ゲームオブジェクトは互いに通信する必要があります。これら2つのことは両方とも発生する必要があります。最初は冗長であるため、メッセージングを使用しません(おそらく、どこかにすべてのオブジェクトのリストがあり、updateそれらを呼び出すだけです)。2つ目は、さまざまな理由でメッセージングで実行できます。
Tetrad、2011年

回答:


8

私は必然的に発明の母であることを完全に信じています。必要が明確で明確でない限り、私は何もコーディングしたくない。イベントメッセージングシステムをセットアップしてプロジェクトを開始すると、間違っていると思います。インフラストラクチャを作成してテストし、プロジェクトのすべての要素を明確に定義し、機能するモジュールを用意して初めて、これらのモジュールを相互に接続する方法に集中できると思います。各モジュールの形状とニーズを理解する前にイベントメッセージングシステムを設計しようとするのは順不同です。

両方のアプローチの長所と短所は何ですか?

一部の人々は、インストールして使用する準備ができている優れたメッセージングシステムがあると主張するでしょう。おそらくこれは本当です。確かに、ニーズに合わせて特別に調整されたカスタムビルドソリューションのパフォーマンスは、汎用メッセージバスよりも優れています。大きな問題は、すでに構築されているものを使用するのではなく、メッセージングシステムの構築にどれだけの時間を費やすかです。明らかに、必要な機能セットを備えたある種のイベントシステムを見つけることができれば、それは非常に簡単な決定です。そのため、決定を下す前に、自分が必要なものを正確に理解していることを確認します。

どちらが他より優れているのですか?

ここでメモリとリソースについて話すことができます。リソースが限られているハードウェア向けに開発している場合、それを大幅に削減するイベントシステムを使用することは確かに問題です。しかし、実際には、問題はあなたが必要とするものに起因すると思います。これは、すでに述べたように、すべての部分がどのように見えるかを見るまでわからないものです。これらのシステムの構築に十分な経験があり、すべての要素がどのようになるかを事前に正確に把握している場合は、この質問にも事前に回答できます。経験したことがあれば、この質問をするつもりはないので、この経験はないと思います。

イベント駆動型ゲームデザインは、すべての分野で普遍的で優れていますか?したがって、モバイルプラットフォームでも使用することをお勧めしますか?

すべての分野で普遍的で優れていますか?そのようなかなり包括的な声明は簡単に拒否されます。オーバーヘッドを追加するものはすべて、ワークロードのシェアを運ぶ必要があります。デザインのオーバーヘッドを保証するのに十分なイベントを使用していない場合、それは間違ったデザインです。

どちらがより効率的で、どちらが開発が難しいですか?

効率は、その実装方法によって異なります。よく開発された伝統的なデザインは、イベントベースのシステムよりも優れています。これは、ピース間の通信をマイクロ管理して、非常に効率的にすることができるためです。もちろん、これはまた、それを完了するために必要な経験と時間の観点から設計することをより困難にし、より効率的にします。一方、この経験がないか、アプリケーションを適切に開発する時間がない場合は、ニーズに合ったイベントベースのデザインを使用する方が効率的です。イベントベースの構造に簡単に適合しないカスタムイベントのニーズがある場合、これはイベントベースの構造の設計を非常に困難にする可能性があります。特に、設計の効率を維持するためです。


こんにちはエリック、私の質問に対するあなたの詳細な意見をありがとう。あなたと他の人の応答を読んでいるように、イベントメッセージを実装しても、全体的なゲームパフォーマンスの向上に奇跡は起こらないでしょう。代わりに、物事を非常に複雑にします。この質問を閉じる前に、もう少し回答をご覧ください。本全体がこのトピックをカバーしていたので、検討するのは良い考えのように見えました。プロジェクトの途中でメッセージを使用するか使用しないかの決定ができ​​るかどうかは、私にはよくわかりません。イベントメッセージを使用する場合、オブジェクトデザイン全体も調整する必要があると思います。
Bunkai.Satori

同意しません。オブジェクト設計全体が十分にカプセル化されている場合は、あらゆる種類のフレームワークで使用できるように十分に柔軟でなければなりません。大規模なプロジェクトでは、各部分が適切にカプセル化されているため、ほとんど作業を行うことなく通信方法を交換することができました。
エリックロバートソン

7

ここでリンゴとオレンジを比較していると思います。ポリモーフィズムの代わりにメッセージングを使用することはありません。おそらく、緩やかに結合されたコンポーネントを接続するためのイベント/メッセージングが必要です。例えば。衝突が発生したときにエンティティからメッセージを送信したり、プレーヤーのスコアを更新したり、効果音をトリガーしたりできます。そのため、これらの個々のクラスは他のクラスを認識せず、メッセージを送信または処理するだけです。

しかし、あなたのゲームは、最も可能性の高い更新ループのどこかを持っているとしているとあなたは以来持っていること、更新ループを、簡単にだけでなく、すべてのフレームを更新する必要があるすべてのゲームのエンティティを更新するために使用することができます。ただし、これはメッセージングの使用を妨げません...

ゲームエンティティを追加/削除するような構造がある場合は、フレームごとに更新メッセージをディスパッチする代わりに、更新ループに含めることもできます。では、メッセージングを使用してゲームのさまざまなサブシステムを接続しているときに、ゲームエンティティでupdateを直接呼び出さないのはなぜですか?イベントのようなシステムのシグナル/スロットの概念(qtの例を参照)も気に入っています。

結論:より良いアプローチはなく、排他的でもありません。


こんにちは、ブンザック。最後に、最初の答えが到着しました。ありがとうございます:-)私がイベントドリブンアーキテクチャについて言及したとき、私はAppliaction、GameView、GameLogicの3つの主要なレイヤーを持つMVCシステムを意味しました。これらのトレイ間のすべての通信は、メッセージングを介して行われます。これは、更新ループを備えた従来のシステムとは大きく異なります。すべてのシステムには異なるアーキテクチャ、いくつかの長所と短所があり、パフォーマンスコストも異なります。したがって、私は、一部の領域では少し優れていると信じています。適切に分析した後、どちらが優れているかを判断できるはずです。
Bunkai.Satori、2011年

3
なぜこれが違うのか分かりません。どこかに更新ループが必要です。MVCを使い続ける場合は、おそらくコントローラーを更新します。その後、コントローラはモデルとビューにメッセージを送ることができます。ただし、コントローラは通常ビューとモデルを知っているため、それらを直接更新することもできます。しかし、これは多態性を置き換えるものではありません。あなたの質問と仮定は非常に理論的に聞こえますが、おそらくいくつかの例のコードまたはいくつかの参照でそれらをバックアップしますか?
bummzack 2011年

上記の本、Game Coding Completeは、仮想メソッドへの直接呼び出しよりもイベントメッセージングを推奨しています。メッセージングシステムはより複雑に見えますが、その利点は、すべてのゲームオブジェクトがゲームの世界をチェックする必要がないことです。ゲームワールドはゲームロジックによって1回だけチェックされ、その後、状態を変更することになっているオブジェクトのみがアドレス指定されます。これは1つの違いであり、コスト削減を意味します。ゲームオブジェクトがメッセージを介して通信する場合、フレームごとに呼び出されることはないため、2つのアプローチは相互に排他的です。
Bunkai.Satori

1
元の質問の下のTetradのコメントを反映する回答に賛成票を投じました。@ Bunkai.Satori「ゲームの世界は一度だけチェックされる」は更新ループであり、更新が必要なものすべてがそれを取得します。イベントメッセージはめったに行われることはありませんが、エンジン(PlayerDied、MonsterDiedなど)で重要なことは、Update()ループですべてのフレームをチェックすることは無駄ですが、 Update()自体をループします。
James

1
第2版​​をお持ちの場合は、メインループの制御という章をご覧ください。第3版でも同じ名前にする必要があります。それは本当にあなたの質問に答えるべきです。
Ray Dey、2011年

4

これは、bummzackの回答に対するコメントとして始まりましたが、長くなりました。

実際に非同期にしない限り(新しいスレッドでイベントをディスパッチ)、オブジェクトはメモを同期的に取得します。イベントディスパッチャーがセル内のリンクリストを含む基本的なハッシュテーブルを使用すると想定すると、順序は、オブジェクトがそのセルに追加された順序になります。

さらに、何らかの理由で関数ポインターを使用することを決定しない限り、メッセージを取得する各オブジェクトはIEventListener(またはユーザーが呼び出すもの)を実装する必要があるため、仮想関数呼び出しを使用しています。イベントは、ポリモーフィズムを使用して構築する高レベルの抽象化です。

ゲーム内のさまざまなシステムを同期するために、ゲーム内のさまざまな出来事のメソッドのランドリーリストを呼び出さなければならない場合や、さまざまなオブジェクトやシステムの反応が原因で、その出来事を明確に定義できない場合、または必要な場合に、イベントを使用します。将来の出来事にもっと反応を加えるために。

それらは素晴らしいツールですが、ブムザックが言ったように、ポリモーフィズムとイベントが同じ問題を解決すると仮定しないでください。


こんにちはBearcdp、返信ありがとうございます。それは私には理にかなっています。私の心には、イベントメッセージに投票することが1つあります。たとえば、シーンには200のオブジェクトが存在します。すべてのオブジェクトでフレームごとの関数呼び出しを使用する場合は、フレームごとにコリジョンがないか200オブジェクトすべてを確認する必要があります(例:もちろん呼び出し間隔を管理できます)。イベントメッセージングを使用すると、gameworldは1回だけ検査されます。5つの衝突がある場合、フレームごとの呼び出しによる200の衝突検出テストではなく、衝突イベントに関するメッセージによって通知されるオブジェクトは5つだけです。あなたの意見は何ですか?
Bunkai.Satori

2
ゲームワールドを調べますか?どういう意味ですか?メッセージの送信に必要な5つのチェックを分離するには、同じ200チェックを実行する必要があります。仮想関数の概念では、ゲームワールドも一度だけチェックされ(各オブジェクトの関数が順番に)、状態の変更が必要な5つだけに移行します...メッセージングシステムのオーバーヘッドなし。
Steve H

1
スティーブHに耳を傾けてください。世界は衝突しません。私は主に、PlayerJump、EnemyHitなどの高レベルのイベントにイベントを使用します。衝突チェックの効率を処理するには、ゲーム内のオブジェクトの物理的な場所を整理するためのデータ構造を選択する必要があります。これにより、衝突をチェックする必要があるオブジェクトとチェックする必要がないオブジェクトを優先できます。衝突したオブジェクトのすべてのペアを特定したら、関連する衝突データ(2つのオブジェクト、速度/位置/法線データなど)を使用してイベントを送出できます。
michael.bartnett

こんにちはSteveとBeardcp、コメントありがとうございます。あなたが書いたものは理にかなっています。イベントメッセージングシステムの実装には多くの可能性があるようです。上記の本に書かれているように、フレームごとの仮想関数の概念を純粋に置き換えることができます。ただし、メッセージングシステムは、フレームごとの仮想機能の概念と共存できます。
Bunkai.Satori、2011年

関数ポインタに関して「なぜ」と言うのですか?これは、最初からイベントシステムを作成したときのイベントシステムの実装方法とほぼ同じです(私はファーストクラスの関数を持つ言語で作業しますが、同じ考えです。関数をイベントハブオブジェクトに渡し、そのオブジェクトがリスナー関数をマップします。イベント)なので、そのアプローチに不利な点があるかどうか疑問に思っています。
ジョッキング

2

どちらか一方を選ぶのはかなり間違っています。一部のオブジェクトはすべてのフレームを呼び出す必要があります。レンダリングしたいオブジェクトがある場合は、フレームごとにそのオブジェクトにレンダーコールを行う必要があります。イベントはこの変更を行うことができません。同じことが時間ベースの物理オブジェクトにも当てはまります。フレームごとに呼び出す必要あります。

ただし、オブジェクト管理オブジェクトやユーザー入力オブジェクトなどをフレームごとに呼び出すわけではありません。フレーム上のすべてのオブジェクトへの大量の仮想呼び出しはひどい考えです。

特定のオブジェクトに使用される設計は、それらのオブジェクトのニーズに基づく必要があり、システム全体のいくつかのイデオロギーに基づくべきではありません

最初の文がより明確になるように編集しました。


こんにちはDeadMG、私に説明させてください:上記のケースでは、デザインは3つの主要な部分に分けられます:アプリケーションレイヤー(ハードウェアアクセス)、ゲームロジック、ゲームビュー。フレームごとにレンダリングされるのはゲームビューです。ただし、ゲームビューでユーザー入力(追跡ゲームでブレーキペダルが押されたなど)が記録されると、処理のために「Car 2 Brake Pressed」というメッセージがゲームロジックに送信されます。Game Logicはこのアクションを評価し、車の動作を計算して、メッセージをゲームビューに送信します:「Car 2 Block Tires」、「Car 2 Move to X、Y」。このようにして、すべての車でブレーキが押されたかどうかをフレームごとにチェックする必要はありません。
Bunkai.Satori、2011年

@Bunkai:イベント駆動型のデザインと、各フレームと呼ばれるデザインがあります。それは私の答えにかなり同意します。
DeadMG

この質問が今日ここで少し物議を醸したので、私はあなたと理解を見つけてうれしいです:-)
Bunkai.Satori
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.