プレーヤーが停止したときに、ローカル入力予測によるプレーヤーのドリフトを停止するにはどうすればよいですか?


14

私は2Dサーバークライアントマルチプレイヤーゲームエンジンに取り組んでいます(こちらで試すことができます)。WebRTCを使用しDataChannelます。(接続はピアツーピアですが、ホストピアはサーバーとして機能します。)

(接続性を除く)最大の問題は、ローカル入力の予測です。通常の操作:キーを押すと、プレイヤーは即座に移動し、どのキーが押されたかをホストに伝え、ホストからデータを受け取り、それを過去の位置と比較します。差異がある場合、位置は時間とともに修正されます。これは、pingが高い場合でも、低いパケット損失またはPDVでうまく機能します。

損失またはPDVがある場合、偏差は大きくなる可能性があります。これは、入力の変更を示す最初のパケットが遅延またはドロップされた場合、ホストが後で検出し、ローカル入力の予測よりも遅れてそのプレーヤーの変更を開始するためだと思います。

プレーヤーが動いている場合は、目立たないため、適用される修正の量を増やします。これは、移動を開始するときと移動しているときにギャップを埋めるようです。ただし、修正が突然停止した場合、修正はより顕著になります。その後、ホストが後で停止したとPDVまたは損失が意味する場合、ホストはオーバーシュートし、少し先に進んでいるというデータを送り返し、修正によりプレイヤーは少しドリフトします。不安定な接続では、プレイヤーはしばしば停止した後に顕著にドリフトします。

私は他のゲームでこれに気づいていません。これをどのように軽減できますか?


3
サーバーを備えたP2Pゲームですか?ここに何か問題があります。
API獣14

おっと、「サーバー」とは「ホストピア」を意味します。
アシュリーズブレイン14

2
プレイヤーの1人がサーバーがピアツーピアにしないように見せかけているからといって、それもピアツーピアモデルのようには見えません。あなたが採用している手法は、間違いなくクライアントサーバー手法です。P2Pでは、すべてのクライアントを完全に信頼する(たとえば、各ピアがプレーヤーの居場所をお互いに尋ねる)か、信頼しない(たとえば、すべてのピアが受信するまで入力を遅らせる)のいずれかです。
APIビースト14

ああ...それは実際に良い点です...私は混乱しました:接続はピアツーピア(これはWebRTCが行うことです)ですが、エンジン自体はサーバークライアントです(ピアの1つは単なるサーバーです) )。いい視点ね。
アシュリーズブレイン14

2
これが私に思い起こさせるのは、私たち自身のAndrew RussellStick Ninjas 開発者がYouTubeログオンしていること、特に予測エラーの修正に関するものです。あなたが説明するドリフトは、そのビデオで起こっていることと非常によく似ており、アンドリューは詳細を語ります。これらは関連しているのでしょうか、それとも同じ問題なのでしょうか?
アンコ14

回答:


8

ネットワーク層には、合意されたクロックが必要です。ゲームの早い段階でクロック値に同意することができ(ドリフトの場合は定期的に再同期します)、ホストは特定のパケットが実際に到着するのにかかった時間とクライアントがアクションを実行した時間を認識します。

ゲームのクロックを同期する1つの可能な方法については、この記事を参照してください。他にもあります。具体的な手段は関係ありません。

問題の後半は、クライアントが入力の適用を停止した時間を過ぎてからサーバーが入力を適用していることです。これには、サーバー上の過去の動きのバッファーと、最後の既知の動きを過ぎたサーバーからの動きの入力を無視するクライアント上のいくつかのロジックが必要です。

まず、サーバーバッファー。サーバーは、プレーヤーから受信した最後の入力のクロックスタンプを追跡する必要があります。また、プレーヤーに適用されるすべての動き、つまり動きのクロックスタンプも必要です。入力が受信されると、入力パケットより新しいクロックスタンプが適用されたすべての最近の動きがドロップされ、すべての動きが入力パケットから再適用されます。したがって、サーバーが何らかの入力に基づいてプレーヤーをオーバームーブすると、更新された入力はそれらの動きをキャンセルし、プレーヤーの新しい位置はサーバーが持っている最新の入力知識に基づいています。

クライアント側では、クライアントは最後に入力をサーバーに送信したことを認識します。サーバーからの各プレーヤーの更新は、サーバーが知っている最後の入力のクロックでタグ付けされている必要があるため、クライアントは入力タグの有効期限が切れたサーバーの更新を無視し、クライアントの予測に固執することができます。最終的に新しいサーバーの更新が最新の入力で届き、クライアントはそれらを修正できます。

サーバーは入力クロックを検証し、不正を防止するために入力クロックが期待値から大きく外れていないことを確認する必要があります。入力クロックは、計算する必要のある半往復時間よりも大幅に大きくしないでください。妥当な範囲([Now-2*RTT,Now]たとえば)にクランプします。

クライアントは、古い入力に基づいてサーバーから更新を取得しますが、それが古いことを知る方法がないため、待ち時間が長い場合、他のプレイヤーのアバターの多くのジッターを見るでしょう。受け取った更新された入力(および履歴の一部のドロップと新しい入力での再生)。あなたのアバターのジッターを見る他のプレイヤーとのこの最後の問題は、実際には修正できません。レイテンシーが低下し、ゲーマーが高レイテンシーの接続に固執すると、たとえ自分のプレーヤーがスムーズに動いていたとしても、他のプレーヤーの多くの不安を感じるでしょう。唯一の修正方法は、より良い接続で、またはレイテンシーの少ないピア/サーバーで再生することです。


1

信頼性の高いUDPメッセージを使用して、ボタンの状態の変化と位置修正のための信頼性の低いUDPメッセージを示しました。基本的に、次の記事は非常に役立ちました:https ://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

約20または30の状態保存のために、位置修正メッセージの到着に応じて一定の時間間隔でプレーヤーの状態を保存することによる動きの予測について述べています。したがって、リモートプレーヤーは、予測手法を絶えず適用することにより、実際にはそれほど遠くない「過去」に住んでいるように見えます。

現在の「画面上の」位置は、Lerp(線形補間)数学を使用して予測位置にスムーズに変換できます。アイデアは、修正パッケージ間の時間ギャップで値を補間することです。そのため、表示されたオブジェクトは常に予測された位置に向かって移動しているように見えます。補間値iについては、「中程度のメッセージレイテンシ」で割った1を「中程度のフレームレンダリング時間」で割った値を使用して、動きが滑らかに見えるようにします。

このシナリオでは、ゲームはすべてのクライアントで計算し、サーバーは時々速度や位置などの値を修正します。

この場合に役立つもう1つの点は、ゲームロジックを最適化して、サーバーとクライアントがプレーヤーの入力に基づいてほぼ同様の動作をエミュレートできるようにすることで、遅延の影響を簡単に無効にできることです。

私は私のプロジェクトで使用したスキーム全体を説明しましたので、あなたの質問に対する答えが見つかることを願っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.