-1

ネットワーク ゲームでのクライアント/サーバー通信のプログラミングについて一般的な質問があります。私は TCP をプロトコルとして使用し、通信は ... 機能しますが、それが効率的な方法であるかどうかはわかりません。

一般に、クライアント側で発生するアクションは、次のすべての手順を実行します。

  1. なんらかのアクション (例: ファイアボールがキャストされる)
  2. [*]このアクションでは、文字列を定義しました (例: #F#270#130#。これは、「F」が火の玉であることを意味し、270 は (たとえば) 角度、130 - の速度を表します)。撃つ火の玉)
  3. 文字列は Client と WaitingQueue の outputpuffer に入ります
  4. 文字列が送信されます
  5. サーバーが文字列を受け取る
  6. [*] サーバーには、文字列の意味を検出できるラインインタープリターが必要です (ここでは、F の意味は何ですか? これは火の玉です!) & コマンドを受信したクライアントに基づいて、一意の ID を追加します。
  7. [*] サーバーは、発生したアクションに基づいてロジックを計算する必要があります (火の玉は誰かにダメージを与えるか、誰かに (すぐに) 命中するか、最初に飛んでいくか?)
  8. サーバーは、すべてのクライアントに発生するアクションの (更新された) 文字列を送信します。(例: 何らかの理由で火の玉の速度が遅くなった可能性があります - ここに更新された文字列があります (#F#12345#270#90# - 12345 は一意のプレイヤー ID です)
  9. クライアントは文字列を受け取ります
  10. [*] クライアントは文字列をコマンドに解決し、それを処理します (アニメーション シーケンスを起動します...)
  11. 最初にコマンドを送信したクライアントは、受信した文字列をwaitingqueue内の文字列と比較します - 等しい場合は何もしません(一部のアクションをスムーズにするため、そうでなければ接続の問題/遅延により、一部のアクションが2回発生するか、pingに基づいて場所から場所へジャンプします

これらすべての手順を実行する必要は本当にありますか? [*] でマークされたすべてのステップで、コマンドごとに新しいラインインタープリター/アクションを定義する必要があるため、各アクションをクライアント側とサーバー側で 2 回コーディングしています。シリアル化可能なオブジェクトの送信について何かを読みましたが、一般的には考え方は同じようです。オブジェクトを送信し、それを解釈して処理する必要があり、オブジェクトを送り返します...

ヒントはありますか?より少ないコーディングで、コミュニケーション全体をよりエレガントに解決するには? またはもう少しソート - さまざまなアクションのこれらすべての #F# #M# #H# タグにより、ますます複雑になっています :)

(実際、私は実際に次のハンドラー/アクションを持っています:

-move -look/rotate -hpchange -firearrow -spawn/disconnect ...)

私が言いたいことを理解していただければ幸いです - 私はそのようにコーディングを続けることができ、何とか機能することを知っていますが、それはあまりにも複雑に思えます.

ありがとう!

4

2 に答える 2

0

ゲームに変更が必要かどうかを判断する前に、いくつかの要因を検討する必要があります。

まず、TCP は最適な通信チャネルですか? UDPと比較しましたか?UDP を使用してネットワークを実装した方が良いでしょうか? いくつかのパケットが失われたとしても問題になるでしょうか? ネットワークが遅い場合はどうなりますか?

次に、サーバーへのポーリング/プッシュの頻度を調べます。これを減らすことはできますか?ゲームはリアルタイムである必要がありますか。ゲームのすべての部分がリアルタイムである必要がありますか。おそらく、特定のことが非リアルタイムになる可能性があります。火の玉はまっすぐに進むので、その位置についてサーバーを更新し続ける必要はありません。その方向と速度を伝えるだけで済みます。ゲームの他のどの側面が非リアルタイムである可能性がありますか. 送信する必要があるのは、プレイヤーの場所とアクションだけです。衝突検出などの他のほとんどのものは、クライアントにオフロードできます。

第三に、キーを押すたびにサーバーに送信する必要がありますか? ユーザーが壁にぶつかり、さらに移動したい場合、クライアントはそれができないことを認識しているため、それらのキー押下をサーバーに送信しません。ユーザーが新しい有効な場所に移動した場合は、サーバーを更新します。サーバーに複数のクエリを送信する代わりに、特定のものをバッファリングして一度にサーバーに送信できますか。つまり、前方に移動し、ジャンプして火の玉を投げる場合、クライアント側で 3 回キーを押すと、次の 500 ミリ秒でバッファリングして送信できますか?

ネットワークのオーバーヘッドが心配な場合は、ビット レベルで作業する必要があります。11 バイトの長さの長い文字列 "#F#270#130#" を送信する代わりに、連続する 3 バイト (24 ビット) を送信するのが理にかなっています。

7 ビットがアクションを表します (127 の異なるアクション)。9 ビットは角度 (1 ~ 512) を表しますが、必要なのは 0 ~ 360 度までです。8 ビットは力を表します。

このバイト形式またはその他のバイト形式は、短くてネットワーク上で使いやすく、よりタイトなコードを生成します。また、バイナリ比較はより高速であるため、サーバー上でのアクション パーサーの記述が容易になりました。つまり、#F# を探す大きな switch ケースの代わりに、最初の 7 ビットを見て、それを int と比較するだけです。

クライアントによって強制的に決定されるのではなく、サーバーがこれを決定できますか? つまり、標準の力、または 2 レベルの力 (これは 1 ビットで表現できるため、はるかに優れています)。これにより、クライアントと悪意のあるユーザーがゴミデータをサーバーに送信するのを防ぎます (999 のフォースなど)。フォースは 0 または 1、つまり速度 10 または 20 のいずれかになります。

于 2013-08-07T14:51:25.223 に答える