RTSゲームプロトコル


18

私はマルチプレイヤーRTSゲームについて考えてきました。私が回避できないと思われる部分は、ユニットの動きを同期させることです。ユニットAを移動してXYをスポットする場合、他のクライアントに中継するサーバーにそれを通信する必要があります。

コミュニケーションがどのように見えるか興味があります。ユニットAをJZからXYに移動していることをサーバーに伝えますか?代わりに、運動座標を座標で伝える必要がありますか?あるクライアントから別のクライアントにユニットの動きを伝える最も効率的な方法は何ですか?

編集

これはstackoverflowからの再投稿された質問です。このサイトはおそらく質問のより良い場所であることがわかりました。

その投稿からのより良い答えの1つ:

クライアントサーバーネットワーキングパラダイムを使用するつもりだと思いますか?その場合、クライアントがユニットの実際の配置を処理することを信頼できないため、そのタスクをサーバーに委任する必要があります。次に、各クライアントのティックごとにコマンドリストを取得し、各ユニットの動きを計算します。これが完了したら、次に各クライアントに関連する各ユニットの位置をリレーします(マップ全体、またはビューごとに)、プロセスを再度開始します。


2
答えは、使用する方法によって異なります。クライアント-クライアントまたはクライアント-サーバー。サーバーへのクライアントは簡単ですが、それは必要と信頼できるサーバーを
ジェムKalyoncu

回答:


25

サーバーから各クライアントへのすべてのユニットの位置を同期する必要はありません。それは取り上げる方法あなたが必要以上の帯域幅を。また、ユニットの位置の内挿/外挿などにも対処する必要があり ます。プロのRTSがクライアント/サーバーを使用することはほとんどありません。

代わりに、プレイヤーのコマンドのみを送信します。プレイヤーがクリックするとすぐにユニットを移動するのではなく、移動コマンドをキューに入れて、将来のある時点(通常は数フレーム)で実行します。全員がコマンドを全員に送信します。数フレーム後、全員がすべてのコマンドを実行します。ゲームは決定論的であるため、すべて同じ結果になります。

欠点は、すべてのプレイヤーが最も遅いプレイヤーと同じくらい遅いことです-コマンドの送信に遅れが出た場合、誰もが遅くなり、追いつくのを待つ必要があります(Starcraft 2では、これは「XXXがゲームを遅くしている「ダイアログ


実際、通常行われるもう1つのことは 、サーバーを完全に排除することです。すべてのクライアントにコマンドを他のすべてのクライアントに送信させます。これは遅れ削減(代わりにあなたから行くコマンドのを- >サーバー- >対戦相手、それはちょうどあなたから行く- >相手) のコードに必要のない別のサーバーから、より簡単にコーディングなります。この種のアーキテクチャは、ピアツーピア(P2P)と呼ばれます。

欠点は、競合を解決する方法が必要になったということですが、ほとんどのRTSではプレイヤーのコマンドが互いに独立しているため、通常はそれほど問題になりません。また、それはうまくスケーリングしません-新しいプレイヤーを追加するたびにすべてのプレイヤーは彼にコマンドを送る必要があります。P2Pを使用してMMO RTSを作成するつもりはありません。


この設定(P2Pを使用してコマンドのみを送信)、Starcraft、C&C、およびAoEを含むほとんどのRTSの動作方法であり、AoEが28.8kbps接続で1500ユニットをサポートできる唯一の方法です。

(AoEのネットワークのイメージ)

P2P RTSを作成するためのいくつかのヒントを次に示します。

  • 明らかな理由から、この設定はゲームで固定ステップ時間を使用している場合にのみ機能します-計算の結果がフレームレートに依存しないようにします!ほとんどの場合、固定ステップの方が簡単に作業できるため、これは問題になりません。
  • これが機能するためには、すべてのコマンドの結果が完全に決定的でなければなりません。
    • これは通常、1つのシステム(32ビットWindowsなど)に制限し、すべてのクライアントに同じ実行可能ファイルを使用するように強制する場合、非常に簡単です。順序付けられていないコレクションを反復処理する場合は、非常に注意してください。等
    • これは、異なるプラットフォームでゲームをプレイ可能にすることを計画している場合(またはLinuxでよくあることです)、クライアントが自分でコードをコンパイルできるようにする場合、非常に困難です。異なるシステムライブラリではrand()cos()などの異なる実装を使用することがかなり保証されているだけでなく、ほとんどすべての浮動小数点演算は問題外ですこちらこちらこちらをご覧ください!その場合は、クライアントサーバーを使用した方がよい場合があります。
  • 少なくともデバッグ中は、すべてのユニットの位置を時々送信して、非同期のバグを検出する必要あります(私を信頼してください)。最終ゲームでそれを保持するかどうかはあなた次第です-ハッキングの試みを検出するために、少なくともいくつかのユニットを同期します(または何らかのチェックサムを使用します)。

良い投稿。同じコンパイラで最適化、デバッグ/リリース、その他のフラグを追加しても、結果が変わる可能性があります。注意してください!
ピーターØlsted11年

14

コマンドの結果ではなく、コマンド自体渡す TCPネットワークRTSを作成しました。たとえば、プレーヤーは移動の順序を指定します。そのクライアントに従って移動順序が有効である場合、サーバーに送信されます。サーバーはそれをすべてのクライアントに送り返し、すべてのクライアントはそれを検証して実行します。

そのため、すべてのクライアントマシンが自分でゲームを実行し、サーバーコードがメッセージを受け入れて、すべてのクライアントに送り返します。クライアントが移動の順序を指定すると、サーバーから返されるまでクライアントは実行を開始しません。

サーバーはコマンドを実行する「ティック」番号も送信します。これは「現在」のティックよりも数ティック先です。これにより、すべてのコマンドをすべてのマシンで同じ「ティック」で実行できます。

この方法の利点の1つは、コマンドを検証するために個々のクライアントマシンに依存しないことです。移動の結果に合格した場合、それをハッキングしてユニットをより速く移動できる可能性があります。すべてのクライアントが同じコマンドを実行する必要があり、1台のマシンが異なるコマンドを実行する場合、それは明らかです。

サーバーに送信する前にコマンドをクライアント側で検証する必要はありませんが、理論的にはネットワークトラフィックを節約します。同じ検証コードを使用して、UIに移動が可能であることを伝えるため、追加のコードを書く必要はありませんでした。

メッセージがどのように見えるかについては。それは私の最初のネットワークゲームだったので、私は超効率に関心がありませんでした。コマンドを文字列として渡しました。コマンドは次のようにフォーマットされます。"<player_id>:<command>:<parameters>"

不自然な例では、移動コマンドは次のようになります "3:move:522:100:200"。プレイヤーは、この手段3に望んでいるmoveユニット522に(100200)。

サーバーは、送信したクライアントを含むすべてのクライアントに、次のようにティック番号を付けてコマンドを渡します"153238:3:move:522:100:200"

その後、ティック153238が実行されると、クライアントはすべてこのコマンドを実行します。


質問にもう少し情報を追加しました。SOからの答えは、あなたが言ったことに反するようであり、私はより細かい詳細を議論したいと思います。
Darthg8r

はい、それは別の方法ですが、コマンドだけではなく、ゲームの状態の大部分を渡すのはもっと手間がかかるように思えます。私のゲームはシンプルで、すべてのクライアントマシンですべてを実行できます。MMOまたはMinecraftのようなものの場合、クライアント側でシミュレーション全体を実行するわけではないため、各クライアントに関連する情報のみを個別に渡します。
フィリップ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.