クライアントとサーバーの両方で物理シミュレーションを実行しますか?


13

ゲームのクライアント/サーバーネットワークアーキテクチャについて学ぶために、マルチプレイヤーの小惑星クローンを実装しています。クライアント/サーバーテクノロジーに関するGafferOnGamesとValveの出版物を読むのに時間を費やしました。2つの概念に問題があります。

  1. 現在、私はbox2dで物理学をシミュレートし、世界の状態をクライアントに毎秒約20回送信する権威あるゲームサーバーを持っています。各クライアントは、受信した最後のいくつかのスナップショットを追跡し、2つの状態間で急いでスプライトの動きを滑らかにします。ただし、それほどスムーズではありません。それはしばらくの間滑らかになり、それから少しぎくしゃくした後、滑らかに戻るなどです。私はTCPとUDPの両方を試しましたが、どちらもほぼ同じです。私の問題が何であるか考えていますか?(注:最初にこれをシングルプレーヤーに実装しました。物理世界を1秒あたり20回のみ更新すると、スプライトの動きは60fpsで完全にスムーズになります)。

  2. 最初の問題を解決するために、クライアントがbox2dシミュレーションも実行し、一致しない場合はサーバーのスナップショットに一致するようにスプライトの位置を更新する必要があると考えました。私のシングルプレーヤーの実装はスムーズなので、これはもっとスムーズだと思いました。これはいいアイデアですか?

    上記の問題が解決しない場合でも、クライアント側の予測に必要ですか?たとえば、プレイヤーが船を動かそうとすると、物理シミュレーションなしで小惑星、壁、または敵の船にぶつかったかどうかをどのように知ることができますか?彼らの船は、衝突するはずのオブジェクトを通過したように見え、サーバーからオブジェクトに衝突したというスナップショットを受け取る前に見えます。

ありがとう!

回答:


10

クライアントとサーバーの両方で間違いなくシミュレーションを実行します。それ以外の遅延は長すぎます。オブジェクトを同じ順序で挿入し、固定の時間ステップを使用し、ポインター比較を回避することにより、シミュレーションが一致することを確認する必要があります。Box2Dでこれを試したことはありませんが、物理シミュレーションのすべてのマシンで同じ動作を実現することは一般的に可能です。通常、すべての数学はIEEE 754 binary32 floatに基づいており、それらの動作は+-*/いくつかの例を挙げると厳密に定義されています。あなたは注意する必要がありますsincosランタイム間で異なる可能性があるため、これは困難です(これは、複数のプラットフォーム用に開発する場合に特に重要です)。また、コンパイラーでフロート最適化の厳密な設定を使用するようにしてください。サーバーからオブジェクトの状態を定期的に送信することにより、オブジェクトを同期できます。不必要なst音を避けるために、差がしきい値より大きい場合を除き、更新しないでください。

頭に浮かぶ1つの問題は、新しいオブジェクトの作成と、それがクライアント間のシミュレーションをどのように変えるかです。これを修正する1つの方法は、サーバーにすべてのオブジェクトを作成させることです。現在のタイムステップがのt場合、サーバーはに追加されるオブジェクトをスケジュールしますt+d。したがって、追加するオブジェクトとそれらをいつ追加するかを示す新しいオブジェクトリストをすべてのクライアントで維持し、事前にサーバーで更新することができます。dが十分に大きい場合、異なる結果のリスクを最小限に抑えます。本当に違いを処理できない場合、そのタイムステップをシミュレートする前に、クライアントに特定のタイムステップの新しいオブジェクトに関する情報を強制的に待機させることができます。


お返事をありがとうございます。box2dが異なるCPUで同じ結果を生成することは保証されていないと思います。これは、デスクトップゲームを作成しているため、私たちのシナリオになります。権限のあるサーバーからの定期的な更新により、違いがわずかであり、簡単に修正できることを願っていますが、試したことはありません。
-Venesectrix

エリンCattoは同期して複数のBOX2Dの世界全体の状態を維持しようとすると、負けバトル(であることを、考えてbox2d.org/forum/viewtopic.php?f=3&t=8462
パベル

ステートメント"IEEE 754 binary32 floats [..]の動作は、+-*/" などの操作に対して厳密に定義されていますが、これは完全に偽です。IEEE-754のこれらの操作はすべて、実装に基づいて異なる可能性があります。詳細はこちらこちらをご覧ください。
BlueRaja-ダニーPflughoeft 14

1
いいえ。完全に真実です。リンクが説明する問題は、x87 fpuのさまざまなモードと超越の実装に関連しています。IEEE 754 binary32 、基本操作に対して厳密に定義されています。正しいモードを設定し、正しい指示を使用して、標準に従うようにするのはあなた次第です。x87 fpuではなく、SSE命令を使用するだけで大​​いに役立ちます。
ラスマス14

4

それらの間の補間は、補間するデータの次のセットを常に持っていることに依存しているため、おそらくそれほど良く見えません。これは、短いラグスパイクがある場合、すべてが追いつくまで待たなければならないことを意味します。

ありますGameDev上の古い記事あなたが最後にそれのためのデータを持っていたポイントを過ぎてオブジェクトの位置を予測するために次スプラインを使用する方法については。次に、その位置を使用し、新しいデータを取得してスプラインを調整して、新しい位置を考慮します。また、おそらく2回目の物理シミュレーションを実行するよりもはるかに安価であり、クライアントを作成する際にクライアントを明示的に実装しているため、信頼できるユーザーを決定する必要はありません。:)


これがケースかもしれません。私がやろうとしているのは、サーバーから3つのスナップショットを受け取るまで遅延することです。ショット1からショット2に急落します。その後、ショット2からショット3に急落します。パケットを逃した場合、理にかなっている場合は1から2ではなく1から3に急落できます。私はまだこれを正しく実装していないかもしれません。記事へのリンクをありがとう!
-Venesectrix

1

私は自分で似たようなことをいくつかやったので、クライアントだけでBox2Dを実行しました。私がやった方法は、クライアントに独自のシミュレーションをほとんど独自に実行させ、すべての同期パケットの現在の速度(および回転)をサーバーに送信することでした。サーバーはこの情報を他のプレーヤーに送信し、プレーヤーは新しく受信した速度を複製されたエンティティに設定します。クライアント間で顕著な違いはなく、非常にスムーズでした。

もちろん、ここでの問題は、エンティティに対する集中制御がないことですが、物理学のサーバー側シミュレーションも同様に行うことで、サーバー側でも同様にできると思います


ご意見ありがとうございます。不正行為を防止するために集中管理が必要になるため、クライアントが実行していると言っていることが可能かどうかを知るために、少なくともサーバーでシミュレーションを実行する必要があります。
-Venesectrix

1

私は個人的にサーバー上でのみシミュレーションを実行し、発生するたびに関連するオブジェクトの線形/角速度/加速度の変更をブロードキャストすることを好みます。特定のオブジェクトが何らかの理由でその物理的特性(前述の速度や加速など)を変更すると、この特定の変更がサーバーからクライアントに送信され、クライアントはその側を変更しますそれに応じてオブジェクトのデータ。

現在の実装に対する利点は、クライアント側の補間の必要性を無効にし、オブジェクトに非常に忠実な動作を生成することです。問題は、この方法はレイテンシーに対して非常に脆弱であるということです。これは、プレーヤーが地理的に離れすぎている場合に非常に大きな問題になります。

質問1に関しては、スナップショットの受信ごとに正確に完全な20秒間隔が存在するという絶対的な保証がないため、問題は待ち時間の変動になると思います。例を示しましょう(ミリ秒単位で測定される時間は "t"です):

1)ゲームの開始からt = 20で、クライアントはスナップショットを受信し、補間を正常かつスムーズに実行しました。

2)t = 40では、サーバーとクライアントの間に待ち時間があり、スナップショットはたまたま実際にt = 41に到着するだけでした。

3)t = 60で、サーバーは別のスナップショットを送信しましたが、レイテンシのためにシミュレーションの1秒がクライアント側で無駄になりました。スナップショットがt = 60に到着した場合、クライアントは40と60のインスタントの補間を行いませんが、実際にはインスタント41〜60で、異なる動作を生成します。この不正確さが最終的な「ジャーキーネス」の原因である可能性があります。

質問2については、オブジェクトの位置を知らせるフレームごとにパッケージを送信することなく、各オブジェクトが実際にクライアント/サーバー同期であるかどうかを効率的に追跡するものを実装すると、アイデアが機能する場合があります。個別の間隔で実行したとしても、質問1の同じ問題で実行されるだけでなく、転送するデータ量が多すぎます(これは悪いことです)。


あなたの最初の段落であなたが言っていることを私が確信していない。シミュレーションがサーバー上でのみ実行され、速度/加速度の変化のみをブロードキャストする場合、クライアントはスプライトを描画する場所をどのように知るのですか?クライアントは、オブジェクトを適切に描画するために、受信した速度/加速度に基づいてオブジェクトをシミュレートする必要があります。私が期待しているものとまったく異なる間隔でスナップショットを受信するのは正しいと思うかもしれません。それに対処する方法はありますか?
-Venesectrix

クライアントは、オブジェクトの初期および現在の位置、速度、および加速度を認識し、それに応じてオブジェクトが(サーバーとは無関係に)考える位置を更新します。それが(遅かれ早かれ与えられた物体の速度/加速度、方向を変更するためにバインドされている)、物理学、衝突検出を行っているサーバーであるため、サーバーは、最終的には、メッセージを介してクライアント上で、このようなプロパティを変更します
UBSophung
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.