サーバー側ゲームループ


8

多くのJavaゲームでは、fpsを制御するためにthread.sleep()を使用しています。サーバーはグラフィックを表示しないので、サーバーのゲームループはデルタ時間を計算するだけで実行し続ける必要がありますか?この例のように:

long lastLoopTime = System.nanoTime();
final int TARGET_FPS = 60;
final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;   

while (gameRunning)
{
   long now = System.nanoTime();
   long updateLength = now - lastLoopTime;
   lastLoopTime = now;
   double delta = updateLength / ((double)OPTIMAL_TIME);

   doGameUpdates(delta);
}

11
「多くのJavaゲームは、fpsを制御するためにthread.sleep()を使用します」男、私は望んでいない。
MichaelHouse

1
@ Byte56私は多くは言いませんが、そのようなことをする人もいます。sleepigは一般的なものですが、そのメカニズムは事前定義されていません。Thread.Sleep最も簡単な方法です。OSの割り込みを待つ人もいます。vSyncをスリープメカニズムとしてカウントすることもできます。
Ali1S232

回答:


6

私がお勧めしない理由はたくさんあります:

  1. コンピュータリソースは貴重です。それらが無料であっても、それらを無駄にするべきではありません。1台のコンピューターで2つ以上のサーバーが同時に実行されている場合を考えてみます。サーバーの単一のインスタンスがすべてのCPUサイクルを消費すると、他のインスタンスは単に失敗します。Surly OSはこのような貪欲な動作を処理しようとしますが、それにはコストが伴います。OSがプロセスを一時停止し、CPUサイクルを他のプロセスに与える場所がわかりません。また、プレーヤーが自分のLANゲームを開始できるように、実際のゲームと一緒にサーバーを解放することもできます。ゲームサーバーを実行するためだけにCPUコアの1つを使用していると、少し面倒です。

  2. ほとんどのゲーム、特別にネットワーク化された同期ゲームは、固定の時間ステップを使用します。クライアント側で何が起こるかを予測できるようにしたいからです。動的タイムステップは、ゲームの単一のインスタンスを実行していて、他のどことも同期されない限り、多くの理由で優れています。ゲームを実行するシステムの能力を最大限に発揮します。しかし、やはりその代償があります。もう一度ゲームを実行すると、どうなるか予測できなくなります。ボックスが別のボックスにぶつかる単純な物理衝突を考えます。時間ステップのわずかな変化でさえ、結果として生じる衝突解決に大きな違いが生じます。

  3. 精度を上げてもゲームは良くならないので、人々があなたが提案したようにThread.Sleepを使う単純な理由があります。ゲームをプレイしているとき、通常、オブジェクトが1ピクセルまたは2ピクセルずれているかどうかはわかりません。したがって、精度を上げても何も得られません。また、サーバー側とクライアント側の両方にネットワーク帯域幅の制限があります。通常、毎秒30〜60を超える更新を送信することはできません。だから、あなたは単にあなたが捨てようとしている状態を計算しなければならない理由を尋ねることができますか?

  4. 精度を上げるとトラブルが発生する場合が多いです。たとえば、モニターにデータを送信しているときにグラフィックバッファーが更新されないように、「垂直同期」を使用する傾向があります(これは粉砕につながる可能性があります)。また、ほとんどのゲームはフロートを主要な数値コンテナとして使用しますが、正確ではありません。数値が2 ^ -20と2 ^ 20の間にあるときは気付かないかもしれませんが、その範囲外では、不正確な動作が見られます。たとえば、10 ^ -5から10 ^ 5を追加しようとすると、単純に無視されます。これらのちょっとしたエラーは通常目に見えませんが、タイムステップを完全に制御できないと、物事が醜くなります。あなたの場合、レンダリングが含まれていないため、更新時間は最大で10 ^ -4程度であると想定します。つまり、100を超える数値の変更はすべて台無しになります。

  5. 一部のゲームでは、予測できない違いをもたらすのはプレイヤーコマンドのみです。したがって、サーバーを使用して、各プレーヤーのコマンドを他のプレーヤーにブロードキャストするだけで済みます。これらの場合、クライアントのいずれかがサーバーに更新を送信するまで単に待つことができます。これらの更新の間で計算するものは何もありません。つまり、クライアントは(ブロードキャスティング以外に)すべてを実行できるので、サーバーはその仕事だけを行い、その他はクライアントに任せます。


ありがとうございます。可変タイムステップは必要ないと思います。もう1つ、睡眠メカニズムとして何を提案しますか?
Wolfrevo Kcats

@WlofrevoKcastこれは完全にゲームのニーズに基づいていますが、ほとんどのゲームでは、内部言語タイマー(またはOS時間割り込み)で十分です。
Ali1S232

4

あなたは読むべき本(?半固定または完全固定のタイムステップ)、この( -あなたの時間刻みを修正ゲームのガファーを)

サーバーロジックにターゲットFPSを含める理由がわかりません。自分に合った固定時間ステップを見つけ、それに従って更新します。

基本的には、ループの内側にもう1つのwhileループwhile (gameRunning)があり、更新の準備ができるまで時間を累積します。次に、一定の間隔で更新を行います。

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