3

ここでいくつか質問があります。

次のメッセージをサーバーに送信するクライアント A がいるとします。「START MOVEMENT FORWARD」。

待ち時間による遅延があるため、サーバーはこのメッセージをすぐには受信しません。

質問 1: ping (またはより良い:往復時間) は、クライアントがサーバーにメッセージを送信して応答を受信するまでにかかる時間です。サーバーがメッセージを受信したことに気づき、応答の送信を開始するまでの時間を無視できる場合 (これは非常に短いはずです)、これは次のことを意味しますか?

  1. クライアントが何かをサーバーに送信するのにかかる時間 = 往復時間 / 2
  2. サーバーがクライアントに何かを送信するのにかかる時間 = 往復時間 / 2

したがって、クライアント A がそのメッセージを送信すると、サーバーは、クライアントがメッセージを送信してから round-trip-time / 2 ミリ秒後にそのメッセージを受信すると想定されます。これは次の質問につながります。

質問 2: クライアントは最初にパッケージを送信し、そのコマンドをクライアント側で実際に実行する前にラウンドトリップ時間 / 2 ミリ秒待機する必要があります (この場合は前進します)。

ここで、サーバーは次のメッセージを近くのすべてのプレイヤーに送信します:「クライアント A は現在進行中です」。これらのクライアントは、クライアント a のキャラクターが動き始めることを確認します。これは、次の質問につながります。

質問 3: 他のクライアントが移動したというメッセージを受信するクライアントは、このメッセージがサーバーによって送信されたことを考慮に入れる必要があります round-trip-time / 2 ミリ秒前? 移動計算のタイムスタンプに使用される現在の時間を round-trip-time / 2 だけ減らす必要がありますか?

私の考えでは、これらの方法はすべて、遅延が考慮されるため、クライアント間の同期が改善されることを確認します。これは物事を行う正しい方法ですか?他の優れたマルチプレイヤー ゲームのほとんどはこれを行っていますか? コメント、提案、代替案、またはランダムだが関連する叫びはありますか? 前もって感謝します。

4

4 に答える 4

10

ほとんどのmmoでは、ラグが発生しない限り、クライアントは主にサーバーとのやり取りなしで移動すると思います。サーバーは、クライアントがサーバーに送信するメッセージを利用して動きを再現します。したがって、たとえばサーバーが遅れると、クライアントはサーバーからのフィードバックの受信を停止し、サーバーが現在いると判断した位置に戻ります。そのため、ラグがひどいときに数フレーム前にジャンプします。このようにして、サーバーは速度も制御できるため、スピードハッキングは行われません. クライアントがサーバーによって決定された速度を超える特定の速度で移動する場合は、余分なフレームをジャンプして戻すだけです。

他のクライアントでは、一定時間内にサーバーからの応答がなければ、まったく移動できません。これは、「フリーズラグ」を経験する時間です。

もちろん、サーバーがクライアントから送信された位置を単純に取得し、それを盲目的に信頼する場合もあります。これらは、テレポート ハッキングに対して一般的に脆弱なゲームです。

他のプレイヤーの位置になると、確かに遅延があります。これは、2 台のコンピューターを使用して、wow などのゲームに接続し、2 つのキャラクターを同時に動かした場合に見られます。両方のコンピューターで、実際に動かし始めた後に非ローカル キャラクターが動き始めることがわかります。

クライアントには通常、何らかの遅延補償があります。そのため、別のプレーヤーが特定の方向に移動して停止した場合でも、クライアントは、方向を変更したか移動を停止したというメッセージをサーバーから受信するまで、そのプレーヤーの動きをシミュレートします。これが、ping が高いときに他のプレイヤーが前後にジャンプできる理由です。これは、ラグスパイクに当たったときにプレーヤーがスライド/実行/立ち去り、クライアントがサーバーから位置を受信したときに実際の位置に戻るように見える理由でもあります.

もちろん、これはエンジンごとに異なりますが、かなり一般的なアプローチです。

編集:サーバーがラグ補正も使用することは非常に一般的であることを追加するのを忘れていました. あなたの射程内にいる誰かに mmo をぶつけた場合、その人はサーバー ビューからの射程外にある可能性があります。したがって、サーバーは両方のクライアントのレイテンシーを取得し、実際にお互いの範囲内にいるかどうかを一致させようとします.

于 2009-09-19T19:30:06.370 に答える
4

これは古い質問ですが、最近同様のコードを作成したので、誰かの助けになるかもしれません。

はい、レイテンシは常に計算に役立ちます。ただし、RTT よりも少し複雑です。往復時間は常に変化しています...ネットワークコードは平均を維持できますが、その平均からの分散は大きくなります。

ローカル クライアント、リモート クライアント、およびサーバーはすべて、アルゴリズムを使用して現在位置を予測します。次のデータは典型的なものに近いです。

  • 時間: t
  • 配置: 位置 (x,y,z) と方向 (x,y,z,w)
  • 移動: 長さを速度 (x,y,z) として方向を表す線形移動ベクトルと、長さを回転速度 (x,y,z) として軸を表す回転移動ベクトル

[T、P、M] セットから simtime を推定するアルゴリズムが必要です。ここでは提供しません。

クライアントが [T,P,M] で船のドライブの変更を登録すると、T+deltaT までサーバーに到達しません。しかし、deltaT が一般的なネットワーク遅延の許容範囲内にある場合、サーバーは「はい、T で発生しました。それを受け入れます」と言うことができます。それ以外の場合は、「許容範囲外です。私の時間 T' に発生しました」と言ってクライアントを修正したい場合があります。この場合、クライアントは、サーバーの修正されたものから、その後に駆動された [T、P、M] のすべての変更をリプレイする必要があります。 (つまり、それらのキューまたはリストを保持する必要があります)。

次のクライアントは、T+deltaT+differentdeltaT でそれを取得します。すでにシミュレートしたものを変更することはおそらくできないため、シミュレーションを遅らせていない場合、リモート シップをジャンプし、ジャーク フレームが表示されます。そのため、リモート ドリブン シップでは、常に 2*typ.deltaT よりも長い時間だけシミュレーションを遅らせる必要があります。一定の遅延、または徐々に変化する遅延である必要があります。遅延が深刻な場合でも、ジャーク フレームが表示されます。

追加の平滑化コードを使用してすべてのジャークを平滑化できますが、問題がどこにあるかを確認できなくなるため、コードに問題がなくなるまで実行しないでください。

適切な同期時間基準が必要です。そこにある多くのコードは、それをかなりずさんに行っています (たとえば、RakNet はあまりうまく行っていません (またはしていませんでした))。ここに良いヒントがあります: 短期的には、すべてのクロックが同じ速度で動作していると推測でき、オフセットが何であるかを把握するだけでよいため、最大オフセットと最小オフセットのウィンドウを保持し、学習するにつれて閉じます。長期的には、クライアントのクロックが速くなったり遅くなったりするのを補正する必要があるため、ウィンドウが開く必要があることが確実にわかっている場合は、ウィンドウを開いてください。単調に増加し、プロセッサ速度 (現在は可変) をキーオフしていないローカル タイムソースを使用する必要があります。

いいえ、ローカルの「アバター」が移動するときにローカル シミュレーションを遅らせないでください。無反応すぎるようです。同期を改善するために少し (おそらく 50 ミリ秒まで) 遅らせることができますが、RTT までずっと遅らせると、ゲームがイライラするほど反応しなくなってしまいます。ローカル遅延のオプションを設定して、それを試してみてください。わずかな一貫した遅延が許容され、同期が改善される可能性があるためです。しかし、それは必須ではなく、多くの問題を引き起こす可能性があるため、そのコードを最後に実行することをお勧めします. (FPS 近接ゲームをしようとしている場合は、これを実行する必要があり、他のすべてのヘルプを取得する必要があります)。

チート防止とシミュレーションの滑らかさについて: まず、クライアントは、公式の位置が変更されたときに、最後の既知の位置から外挿するだけではいけません。調整ベクトルを登録し、スムーズにするために古いパスから新しいパスにゆっくりと移動する必要があります(ただし、上記のように、このコードを最後に実行しないと、他のバグがマスクされます)。第二に、サーバーは幅広い遅延を許容する必要があります...同じイーサネット上のマシンでも、パケット遅延は通常5ミリ秒から100ミリ秒程度です...それはかなりの範囲です. もちろん、それを切り捨てて、「T に移動したと言うのに、T + some_large_number でパケットを受け取ったと言うなら、あなたは過去を調整しようとしていて、私に嘘をついていると思います」と言う必要があります。人々を正直に保つために、some_large_number は平均 RTT よりも大きくすべきではありません。

シミュレーションが厳密に同期されることはありません。それらはインターネット上で 400 ミリ秒以内にとどまる必要がありますが、30 秒以上の遅延が発生している間は確かにそれを外れます。まれではないため、それを許容する必要があります。インターネットが銅線の光の速度によって制限されていることを考えると、遠方のクライアントの場合、一方向の遅延は通常、少なくとも 100 ミリ秒、多くの場合 500 ミリ秒以上になると常に予想できます。

したがって、インターネット上で近接 FPS ゲームを作成しようとしないことを強くお勧めします (一部の大企業は試みますが、常に問題が発生します)。投射物を使用している場合 (一方のシミュレーションでは高速に実行し、他方のシミュレーションでは低速で実行する)、タイミングがずれていてもオンに見えるようにするためのトリックがあります。また、FPS ゲームでは、ヒット検出は攻撃者のシミュレーションに基づいているというルールが使用されています... 攻撃者がターゲットで死亡したことを知ってミスした場合、防御側が邪魔にならなかったことを知ってヒットした場合、より間違っていると感じます。いずれかの方法。どちらかを選択する必要があり、心理的にはそのように行われています。メレーには、率直に言って不可能なレベルの同期が必要であり、ほとんどのゲーム会社は MMORPG FPS メレーには触れず、代わりにオート ターゲットを使用します (Mortal Online をプレイしてみてください。

幸運を。

于 2010-10-18T07:03:15.983 に答える
1

Q1: それは私には正しいように見えます。

Q2: 私が過去にこれを行った方法は、応答性を感じさせたい場合は、クライアントのシミュレーションで即座にアクションの実行を開始し、サーバーは、ユーザーがアクションを開始したときにゲーム時間で順方向にシミュレートします。つまり、クライアントはゲーム シミュレーション時間の何ミリ秒で開始したかを知っているため、サーバーはその時間に開始することもできます (注: これは常にサーバーの現在のティックから時間をさかのぼるため、時間を遡って状態を保存する必要がありますこれをする)。

Q3: クライアントが実際に知る必要があるのは、時間 X でシミュレートしていることだけです。サーバーは、一連のイベント {A,B,C} が時間 {X,Y,Z} に発生したと言っています。その後、クライアントとサーバーは同じ情報を使用して順方向にシミュレートし、通常は同期を維持できます (同時競合が発生した場合を除く)。そのような場合、サーバーに物事を再同期させるので、通常はかなり狭い誤差範囲内に収まり、ほとんどスムーズなエクスペリエンスになります.

遅延の認識を改善することが目標である場合は、クライアントを信頼してみてください。

于 2009-09-28T20:45:57.553 に答える