マルチプレイヤーゲームで時計を同期させる方法は?


8

Apple Game Centerを介してメッセージを交換できるクライアントが2〜3人います。

必要な唯一の同期は、ゲームを同時に開始することです。

これには、クロックの同期が関係していると思います。これを達成するには?


3
簡単に言えば、「できない」ということです。デバイス間の通信の避けられない(一貫性のない)遅延は、1つのデバイスが「今は12:00:00.00だと思います」と言ったとしても、12:00:00.10〜12:00:05そのメッセージが別の場所で受信される時間。サーバーベースのモデルでは、サーバーに「ゲーム開始」メッセージを同時にクライアントに送信させるよりもはるかに優れた方法はありません。
Steven Stadnicki

完璧を必要としないのは良いことです。何もしないよりも上手に行うには?たぶん:各プレーヤーは「START」メッセージを送信し、他のすべてのプレーヤーからSTARTメッセージを受信するとすぐに開始します
GameCoder

1
@StevenStadnickiネットワークの遅延により、これが不可能になることはありません。一般的な問題は「クロック同期」と呼ばれ、よく研究されています。(ただし、エンドポイントのみを制御する場合、遅延の非対称性を説明することはできません。)
Praxeolitic

私はあなたの問題を誤解しているかもしれませんが、クライアントに送信するメッセージに将来の開始時刻をわずかに示すだけではいけませんか?時間がnowあり、メッセージを送信して正確にnow + halfSecondそれから開始する場合、すべてが0.5秒以内にメッセージを受信し、システムクロックが正しく同期されている限り、それらはすべて同時に開始されます。
マーク・

回答:


12

スティーブンのコメントは正しいです。これは理論的に不可能です。

幸い、実際には近づくことができます。これがNTPのようなものです。

たとえば、「今すぐ開始」と言って3つのクライアントにメッセージを送信するだけではなく、いくつかのpingメッセージを事前に交換して、クライアントにメッセージが届くまでの時間を測定し、開始メッセージを送信するときに、 「今すぐ開始」の代わりに「Xミリ秒で開始」と言って、メッセージが到着するまでのさまざまな時間に合わせてXを調整します。

例えば。:

  • クライアント1にメッセージを送信し、20ミリ秒後に応答を受け取ります。クライアント1にメッセージが届くまでに約10ミリ秒かかると思います。
  • クライアント2についても同じことを行い、28ミリ秒後に応答を取得します。そのため、送信時間は約14ミリ秒になる可能性があります。
  • つまり、「50msでゲームを開始する」というメッセージをクライアント1に送信し、「46msでゲームを開始する」というメッセージをクライアント2に送信します。クライアント2は約4ミリ秒後にメッセージを受け取りますが、ゲームを開始する前に4ミリ秒待機します。

インターネット経由でメッセージを送信するのにかかる時間はさまざまであり、各方向で異なる可能性があるため、これは同期を保証できません。1つ目は、測定を数回実行して中央値を読み取ることで、影響を減らすことができます。2番目の方法はトリッキーであり、理論的には解決できない可能性があります(現在のところ、証明を思い出せません)。良いニュースは、おそらくそれほど多くの正確さを必要としないということです。


おそらく、同期中のアプリのアクティビティを制限する必要があります。現在、各描画フレームでネットワークサブシステムにCPU時間を割り当てています。フレームレートが30 FPSの場合、とにかく、1/30 = 33 msでpingに応答します。また、私は...)(33ミリ秒、または「TCPスタックの時間を受ける」との違いと私の現在のMilisecondTicksを追加することができます
GameCoder

2
プレイ中にシステムをフレームごとに正確に同期させることを希望している場合、それは負けたゲームであり、今はあきらめるべきです。時計と待ち時間はずれ、情報の移動には常に時間がかかります。何をしようとしても、おそらくこのレベルの同期は必要ありません。
カイロタン2012

私たちはポイントを逃していると思います。煩わしいのは完璧ではなく、ユーザーエクスペリエンスです。これは良いか良いかもしれませんが、私はもっと良いと思います。それでおしまい。
GameCoder

2
優れたユーザーエクスペリエンスには、正確な同期は必要ありません。これが、ほとんどのゲームがそれを試みない理由です。
カイロタン

1
各プレイヤーが自分のバットをコントロールすることは理論的に不可能です。なぜなら、その情報が他のコンピューターに到達するのにゼロ以外の時間がかかり、その間、2つのサイドが異なる情報を持っているからです。代わりに、違いに対処する方法を見つけます。あなたの問題は、他のペースの速いオンラインゲームと実際には何の違いもありません。このサイトでのネットワーキングの処理方法については、他にもいくつか質問があります。一つはここにある:gamedev.stackexchange.com/questions/22444/...
Kylotan

3

前述のように、これは不可能であるため、別のアプローチを試します。

専用サーバーがない場合は、参加するクライアントを1つ選択してホストにします(必要に応じて転送できます)。

これでホストは、ヒット検出、AIコントロール、在庫処理などのすべての重要なゲームロジックと、時間追跡(つまり、ゲーム時間の指示)を実行します。

他のクライアントはホストとの同期を維持しようとし、期待値を推定または概算しようとします。ラグが増加したり、パケットが失われたりすると、状況が不安定になる可能性がありますが、追いつくのは簡単で、基本的には次の更新を待つだけです。

ほとんどのゲーム(特にFPS)は、プレイヤー自身の動き、発砲されるショットなどについて独自のローカル計算を行うことでこの事実を隠し、ゲームの遅延を回避しています。すべてはまだサーバーデータに基づいて修正されます。これは、混乱を招く可能性があります。たとえば、自分が敵を撃っているのを見るのと同じですが、(敵が命中することなく)死ぬのと同じ瞬間ですが、それでも完全同期よりはるかに優れたアプローチです。


それでもすべてを同期したままにする場合は、おそらく何らかのステップまたはフレームカウンターを作成する必要があります。そのため、すべてのクライアントが1つのロジックステップのみを処理してから、データを同期します。これは両方の帯域幅になることに注意してください。集中的でラグが大きいので、他に大量のデータがあり、ゲームプレイがターンベース(たとえば、砲兵/ウォームスタイルゲーム)でない限り、これを行うことはお勧めしません。


1

NTP [Stratum 2]プロトコルを使用して、すべてのクライアントとサーバーのシステムタイマーを同期することをお勧めします。サーバーは、すべてのタイマーが0:05:00に達したときなど、指定された時間にゲームを開始するコマンドを送信します。このアプローチでは、3〜4 msの正確な同期が得られるはずです。

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