12

私は約 10 年間ゲームをプログラミングしていません (最後の経験は DJGPP + Allegro でした) が、週末に XNA をチェックして、それがどのように形成されているかを確認しようと思いました。

かなり感銘を受けましたが、ゲーム エンジンの組み立てを続けていると、(おそらく) 基本的な質問があります。

ゲームを動かすために、C# のデリゲートとイベントにどの程度依存する必要がありますか? 私はアプリケーション プログラマーとして、デリゲートとイベントを頻繁に使用しますが、そうすることに大きなオーバーヘッドがあるかどうかはわかりません。

私のゲーム エンジンでは、ある種の「チェイス カム」を設計しました。これは、オブジェクトに取り付けて、オブジェクトに対する相対的な位置を再計算することができます。オブジェクトが移動すると、追跡カムを更新する方法が 2 つあります。

  • メイン ゲーム ループに「UpdateCameras()」メソッドを用意します。
  • イベント ハンドラーを使用して、チェイス カムを object.OnMoved にサブスクライブさせます。

私は後者を使用しています。イベントを連鎖させ、エンジンの大部分を適切に自動化できるからです。突然、巨大で複雑なものが、一握りの 3 ~ 5 行のイベント ハンドラーに落とし込まれます...その美しさ。

ただし、ナノ秒ごとに起動するイベント ハンドラーが大幅な速度低下になる場合は、それを削除してループ アプローチを使用します。

アイデア?

4

7 に答える 7

10

イベントをサブスクライバー リストと考える場合、コード内で行うことは、サブスクライバーを登録することだけです。これを達成するために必要な命令の数は、CLR レベルでは最小限になる可能性があります。

コードを汎用または動的にしたい場合は、イベントを呼び出す前に、何かがサブスクライブされているかどうかを確認する必要があります。C# と .NET のイベント/デリゲート メカニズムは、(CPU に関して) 非常に少ないコストでこれを提供します。

すべてのクロック サイクルに本当に関心がある場合は、一般的/動的なゲーム ロジックを記述することはありません。これは、保守可能/構成可能なコードと完全な速度の間のトレードオフです。

よく言えば、それが問題であることを証明できるまで、イベント/デリゲートを支持します。

それが問題であるかどうかを本当に知る唯一の方法は、コードをプロファイリングすることです。これは、どのようなゲーム開発でも行う必要があります。

于 2008-09-15T15:41:23.603 に答える
4

C# のイベントは、キューに入れられた非同期イベント (Windows メッセージ キューなど) ではないことに注意してください。それらは基本的に関数ポインタのリストです。したがって、イベントを発生させても、関数ポインターのリストを反復処理してそれぞれを呼び出すよりもパフォーマンスが低下することはありません。

同時に、このため、イベントが同期していることを認識してください。イベントリスナーが遅いと、イベントを発生させるクラスが遅くなります。

于 2008-09-15T19:19:09.917 に答える
2

ここでの主な質問は、「C# デリゲートとイベントの使用に関連するオーバーヘッドはどれくらいですか?」のようです。

通常の関数呼び出しと比較して、イベントのオーバーヘッドはほとんどありません。

デリゲートを使用すると、暗黙的で隠れたガベージが作成される可能性があります。特に XBox360 では、ガベージがパフォーマンスの問題の主な原因になる可能性があります。

次のコードは、1 秒あたり約 2000 バイト (60 fps) のガベージを EntityVisitor オブジェクトの形式で生成します。

    private delegate void SpacialItemVisitor(ISpacialItem item);

    protected override void Update(GameTime gameTime)
    {
        m_quadTree.Visit(ref explosionCircle, ApplyExplosionEffects);
    }

    private void ApplyExplosionEffects(ISpacialItem item)
    {
    }

ガベージの生成を回避する限り、デリゲートはほとんどの目的で十分に高速です。隠れた危険性があるため、私はそれらを避け、代わりにインターフェイスを使用することを好みます。

于 2008-09-17T04:09:39.880 に答える
1

XNA では、インターフェイス、イベント、およびデリゲートを使用して、XNA で記述されたものを駆動することをお勧めします。これを設定する GameComponent 関連のクラスを見てみましょう。

答えは「気持ちいいくらい」です。

少し詳しく説明すると、たとえば、gamecomponent クラスから cameracontroller クラスを取得して継承し、それを Game.Component コレクションに追加するとします。次に、カメラ クラスを作成して、カメラ コントローラーに追加します。

これを行うと、cameracontroller が定期的に呼び出され、適切なカメラまたは複数のカメラを選択して有効にすることができます。

以下にその例を示します (彼のチュートリアルはすべて優れています): ReoCode

于 2008-09-15T15:41:27.787 に答える
1

実際の仕事から離れた余暇には、XNA も学んでいます。

私見 (同僚に尋ねると、それほど謙虚ではありません) は、イベント ハンドルのオーバーヘッドが、レンダリングなどのゲーム内の他の要素によって圧倒されるということです。通常の .Net プログラミングでイベントを頻繁に使用することを考えると、基礎となるコードは適切に最適化されているはずです。

正直なところ、UpdateCameras メソッドを使用するのは時期尚早の最適化かもしれません。イベント システムには、おそらくカメラ以外にも用途があります。

于 2008-09-15T15:42:28.640 に答える
1

パフォーマンスに関するイベントの影響を検討する前に、まずイベントが必要かどうかを評価する必要があります。

あなたが本当に追跡カムを最新の状態に保とうとしていて、それが単なる例ではないと仮定すると、あなたが探しているのはイベントではありません (イベントは同じようにトリックを行うかもしれませんが)、アバターをフォローしている場合、それはたいてい動いています。

私が非常に効果的だと思ったアプローチの 1 つは、階層変換を使用することです。これを効率的に実装すると、そのようなシステムの恩恵を受けるオブジェクトはカメラだけではなくなります。目標は、オブジェクトの座標空間内にカメラを維持することです。追跡。

カメラがオブジェクトを追跡する速度と方法にある程度の弾力性を適用したい場合、このアプローチは最善の方法ではありません。そのためには、更新呼び出し、参照、およびいくつかの基本的な加速と抵抗の物理を使用するのが最善です。

イベントは、ときどきしか発生しない、またはアプリケーションのさまざまな側面に影響を与えるもの (キャラクターの死など) に役立ちます。おそらく、多くの異なるシステムがそのようなイベントを認識し、統計を削除し、AI を制御し、このような場合、これが発生したかどうかを常にチェックする必要があるすべてのオブジェクトを追跡することは、イベントをスローして、関心のあるすべてのオブジェクトにイベントが発生した場合にのみ通知するよりもはるかに効果的ではありません。

于 2012-05-28T23:17:39.743 に答える
1

余談ですが、 Allegroの最初の開発者であるShawn Hargreavesが XNA チームの主要な開発者の 1 人であることに興味があるかもしれません :-)

于 2008-09-15T20:56:30.120 に答える