ゲーム開発のためにネットワークを介してクロックを同期する方法は?


10

時間ベースの要素が多いゲームを書いています。私は時間を使用して、ネットワークが停止し、パケットが通過していないときのプレーヤーの位置(およびパケットが受信されるまでの時間と受信されない時間)を推定します。それは、プレイヤーが方向を選択して動きを止めることができないという意味でパックマンタイプのゲームです。そのため、システムは理にかなっています(または少なくとも私はそう思います)。

だから私は2つの質問があります:1)ネットワークに遅延があるので、最初にゲームのクロックをどうやって同期させるのですか?2)それらを同期せず、それらが同じであると想定しても大丈夫ですか(私のコードはタイムゾーンに依存しません)。これは、人々が時計を変えてチートするような非常に競争の激しいゲームではありません。

ゲームはJavaとPythonでプログラミングされています(プロジェクトとして並行開発)


7
ルックアップntp
ラチェットフリーク

5
この質問はすでにgamedev.stackexchange.comでカバーされていると思います、または少なくともそこに属しています。
congusbongus 2013年

1
@CongXu:よくわかりません。これは通常ゲームで行われるタスクですが、ゲーム開発に固有のものではありません。他の多くの分散システムでは、同期クロックが必要です。
Jan Hudec 2013年

2
IPv4オプションのTIMESTAMPを使用しようとしましたか?詳細情報であるlinux.die.net/man/7/socketそこからのlinux.die.net/man/3/cmsgで小さなプログラム例当時とpdbuchan.com/rawsock/rawsock.html前の最後の1 IPv6セクション。
ott-- 2013年

2
ゲーム(アプリケーション)がシステムクロックに触れないようにする必要があります。
モニカの復活-M.Schröder2013年

回答:


9

システムの時計を同期させることは間違いなく問題だと思います。ユーザーはあなたがシステム設定に触れることを期待しておらず、多くのシステムはあなたに触れさせることすらしません。

必要なのは、タイムスタンプを片側の時計から反対側の時計に変換するための相関関係を持つことだけです。一方、プレーヤーの位置を予測するために使用する場合は、この相関をかなり正確にする必要があります。たとえば、少なくとも100分の1秒までです。システムクロック、ランダムマシン間でこれほど適切に関連付けられることはありません。そのため、ネットワーク帯域幅を節約するために、おそらく他のメッセージに埋め込まれているNTPテーマのいくつかのバリエーションを使用して、自分で相関を確立する必要があります。

基本的な考え方は、送信した各パケットでタイムスタンプを送信したことと、シーケンス番号と、反対側から最後のパケットを受信したときのタイムスタンプです。これから、往復を計算します。たとえば、パケットQが1000で送信され、パケットPが500で受信されたと言う場合、0でパケットPを送信し、800でQを受信して​​いる場合、往復は(800-0 )-(1000-500)=300。非対称性を知る方法はないので、パケットはどちらの方向にも半分(150)ティックを取ると仮定します。そして、そのリモートタイムスタンプは、ローカルよりも1000-(800-150)= 350ティックだけ進んでいます。往復は異なります。クロックがかなり正確であると想定する場合は、相関の長期平均を使用する必要があります。

クロックにはシステムクロックも使用しないことに注意してください。それらは途中で再同期され、トラックから外れることがあります。clock(CLOCK_MONOTONIC)UnixまたはGetTickCountWindowsで使用する必要があります(これらのAPIが現在JavaまたはPythonでどのようにラップされているかは不明です)。


注:SO_TIMESTAMPソケットオプション(質問のコメントでott--で言及されているsocket(7)を参照は、パケットを受信するイベントループのレイテンシの影響を分離するのに役立ちます。努力する価値があるかどうかは、必要な精度の高さに依存します。


1

どのプレイヤーの時計が正しいのか、どうやって分かりますか?そうではないので、基準クロックを使用してください

NTPはここではやりすぎです。必要なのは〜1秒の精度だけです。そのため、rdateを使用するか、多くのクロック同期アルゴリズムの 1つから何かを選択します。

方法を選択したら、各プレーヤーのマシンにその方法ごとの時間を(システムクロックを変更せずに)取得させます。参照UTC時間とプレーヤーのシステムクロックUTC時間との違いは、実際のオフセットです。たとえば、ボットの動きや光線追跡の弾丸を推定するために時間関連の計算を行うときは常に、システム時間を取得した後にこのオフセットを考慮に入れます。UTCを使用すると、タイムゾーンの要素がなくなります。


1

このために、NTPを使用したり、システムクロックに近づいたりしないでください。この要件を実際に調べると、次のニーズがあることがわかります。

  • 時間ベースのものを進めることができるように、前のフレームから経過した時間。これは、両方の速度が異なる場合、クライアントとサーバーで異なる場合があります(たとえば、サーバーが20Hz固定(または何でも)で実行されるが、クライアントが望みどおりに高速で実行できる場合があります)。
  • 現在のマップが開始してからの経過時間。これはゼロベースのタイマーであり(起動時にクライアントとサーバーの両方で0に初期化するだけ)、サーバーの時間は「マスター」と見なされるため、サーバーはこの時間の現在のビューをフレームごとにクライアントに送信します。それはサーバー上で実行されます。これは、現在のサーバー時間を取得してサーバーが起動した時間を引くか、上記のフレームごとの時間を累積することによって取得できます。上記のクライアント側のフレームごとの時間は、任意の2つの連続するサーバーフレーム間の補間ポイントを生成するためにも使用できます。
  • 他のすべての時間がそこから進む参照「基準時間」。これは(ただし、すべてのゲームタイプで同じである必要はありません)クライアントとサーバーの両方で同じであり、ゲーム(または現在のマップ)の開始時に初期化されますが、その後は変更されません(新しいゲームまたは新しいマップでない限り) -開始されます)。

これは簡略化された概要です-レイテンシ/ドロップされたパケットなどの問題に対処するつもりはありませんが、それは全体が基づいているべき基本的なフレームワークです。

最後の項目で必要に応じてタイムゾーンを使用できますが、システムクロックの近くに行ったり、さまざまなタイムゾーンなどの問題を心配する必要はありません。重要なことは、実際の経過時間は高分解能のゼロベースのタイマーを使用して測定されるため、時間帯の違いに完全に依存しないということです。サーバー上の実際の現在時刻を確認したいですか?経過時間を参照基準時間に追加するだけで取得できます。クライアントも同様です。

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