タンクゲーム2D(Unity)用のオンラインゲームサーバーを構築しようとしています。私のゲームでは、2〜4人のプレイヤーが戦車を操作し、お互いに戦います。
Unityネットワーキングを使用しようとしましたが、部屋のプレーヤーの1人を選択して「サーバー」にする必要があるため、ゲームにはあまり適していませんでした。これは、将来の開発にあまり柔軟ではありません(たとえば、「サーバー」が終了しました。他のプレイヤー間の接続を維持するには、多くの作業を行う必要があります)。
次に、サーバーとクライアントの通信用にNodejslàsocket.ioを使用して独自のサーバーを構築しようとしました。非常に簡単です。あるデータからデータを受信し、他のデータにブロードキャストします。物理的な部分が入るまでは正常に機能しているようです。サーバーは、何かがヒットまたは爆発したとクライアントが言ったときにクライアントを信頼し、それを他のクライアントにブロードキャストする必要があります。不正なクライアントは言うまでもなく、ネットワークの遅延により、クライアントの物理シミュレーションは異なります。たとえば、このクライアントで戦車が攻撃されたとしても、もう一方のクライアントの壁の後ろで覆われて生き続ける必要がありますが、遅延のため、背後の戦車が弾丸を捕まえて爆発します。このような場合、サーバーはどちらをリッスンするかを認識していません。
結論として、ゲームサーバーに関する提案が必要です。
一部のゲームサーバーサービス(Photon、Unityネットワーキングなど)はサーバーにゲームロジックを実装する方法を気にしないように見えるので、私は正しい方向に進んでいますか?そしてそれは彼らを権威あるサーバーではないのでしょうか?
私はこの分野に非常に新しいです、何でもありがたいです!
NodeJSで行ったように、ゲーム用に独自のサーバーを作成することをお勧めします。私が知っているソリューションのほとんどは、使用するのが非常に難しく、あなたが望むすべてを行うことができません。
たとえば、ブリザードゲームのハースストーンはクライアント用のUnityに基づいており、カスタムメイドのサーバー側があります。
ゲームサーバーの作成方法に関するアドバイスをいくつか紹介します。
物理的な部分が入るまでは正常に機能しているようです。サーバーは、何かがヒットまたは爆発したとクライアントが言ったときにクライアントを信頼し、それを他のクライアントにブロードキャストする必要があります。
サーバーを作成するときは、クライアント側ではなくサーバー側ですべての重要な決定を行う必要があります。パーティーを開始するのはサーバーであるため、サーバーには次の情報が必要です。
これで、クライアントは常に次のように非常に小さな信号をサーバーに送信する必要があります
ユーザーのアクションとユーザーのデータに基づいて、サーバーはゲームの「シミュレーション」を実行できます。
これにより、サーバーは何かがいつ発生するかを認識し、何が発生するかを決定します。クライアント側の情報に依存するのではなく、プレーヤーの希望するアクションを受け取るだけです。
ただし、おっしゃるように、遅延やその他のネットワーク要因のために、クライアントはサーバーに過度に依存することはできません。最近のゲームでは、クライアントはサーバーと同じプレーヤーに関するデータを持っており、何が起こっているかを画面に表示するためにサーバーに常に依存しているわけではありません。
一部のオンラインゲームをプレイした場合、サーバーとの接続が失われると、プレイを継続できる時間が少しありますが(移動、撮影など)、自分以外は何も移動しないことに気付いたかもしれません。これは、サーバーの情報がなくても、クライアントがアクションに基づいてゲームを「実行」し続けるためです。
ただし、クライアントからプレーヤーに表示される内容とサーバーのシミュレーションで行われる内容との大きな違いを回避するために、クライアントとサーバーは一定の間隔で「同期」します。
たとえば、左に移動することにした場合、クライアントは移動速度を知っているため、サーバーに依存せずに移動を表示できます。
同期が発生すると、サーバーはクライアントに重要な情報を送信し、クライアントは現在表示されている情報をサーバーが送信する情報に変更します。
左の移動の例では、サーバーとクライアントで移動速度が異なる場合、クライアントが同期命令を受信すると、プレーヤーが表示された位置から別の位置に「テレポート」されることに気付くでしょう。これは、一部のパケットが失われた場合、または待ち時間が長い場合にも発生する可能性があります。
サーバー側とクライアント側の両方でオンラインゲームを作成する場合、レイテンシーの処理は大きな課題であり、この質問のトピックではありません。
要約すると、サーバーは
この助けを願っています=)
さて、あなたのゲームでは、プレイヤーはアクションMOVEしか使用できないと仮定します。
ユーザーがサーバーに接続すると、ゲームを起動できます。ユーザーは移動できるため、2Dマップがあり、ユーザーにはサイズ、初期位置、速度があります。したがって、サーバーは新しい「GameParty」を開始し、上記のデータを初期化する必要があります。この例では、次のデフォルト値が設定されていると仮定します。
map_width = 512;
map_height = 512;
user_width = 2;
user_height = 2;
user_speed = 1;
user_posx = 20;
user_posy = 20;
クライアントが移動したいとき、彼は移動したいというパケットをサーバーに送信します。クライアント<->サーバー通信には任意のプロトコルを使用できます。私はバイナリプロトコルを使用しますが、Jsonを使用するとします。
{action: move; value: left};
これにより、サーバーはユーザーが左に移動したいことを認識します。したがって、サーバー側で新しい位置を取得するには、user_posx
を値user_speed
だけ減らす必要があります。この位置がマップの端にある場合は、2つの選択肢があり、ユーザーをマップのもう一方の端に表示してアクションを禁止します。
一定の時間間隔で、サーバーはクライアントにプレーヤーの現在の位置を送信します。