1 秒あたりの表示フレーム数をゲーム ロジックから独立させるにはどうすればよいですか? つまり、ビデオ カードのレンダリング速度に関係なく、ゲーム ロジックは同じ速度で実行されます。
ベストアンサー1
この質問は、ゲーム エンジンの設計方法についての誤解を少し明らかにしていると思います。ゲーム エンジンは非常に複雑で、正しく設計するのが難しいため、まったく問題ありません。
フレーム レートの独立性と呼ばれるものが必要なのは正しい印象です。ただし、これはレンダリング フレームだけを指すわけではありません。
シングル スレッド ゲーム エンジンのフレームは、一般的にティックと呼ばれます。ティックごとに、入力を処理し、ゲーム ロジックを処理し、処理の結果に基づいてフレームをレンダリングします。
やりたいことは、ゲーム ロジックを任意の FPS (フレーム/秒) で処理し、確定的な結果を得ることです。
これは次の場合に問題になります。
入力を確認します: - 入力はキー「W」で、これはプレイヤー キャラクターを 10 単位前進させることを意味します。
プレイヤーの位置 += 10;
これをフレームごとに実行しているので、30 FPS で実行している場合は 1 秒あたり 300 ユニット移動することになります。
しかし、10FPSで実行している場合は、1秒間に100ユニットしか移動しません。したがって、ゲームロジックは次のようになります。ないフレームレートに依存しません。
幸いなことに、この問題を解決し、ゲームプレイロジックをフレームレート非依存にすることは、かなり簡単な作業です。
まず、各フレームのレンダリングにかかる時間をカウントするタイマーが必要です。この秒数 (つまり、ティックを完了するのに 0.001 秒) は、フレーム レートに依存しないようにしたい値に掛けられます。この場合、次のようになります。
「W」を押しているとき
プレイヤーの位置 += 10 * フレームタイムデルタ;
(デルタは「何かの変化」を意味するおしゃれな言葉です)
したがって、プレイヤーは 1 ティックで 10 単位の一部を移動し、1 秒のティックが経過すると、10 単位すべてを移動したことになります。
ただし、加速する車両など、変化率も時間とともに変化するプロパティの場合、この方法は役に立ちません。この問題は、「Verlet」などのより高度な積分器を使用することで解決できます。
マルチスレッドアプローチ
質問に対する回答にまだ興味がある場合 (私は回答していませんが、代替案を提示しています)、ここにあります。ゲーム ロジックとレンダリングを別のスレッドに分離します。ただし、これには欠点があります。ゲーム エンジンの大部分がシングル スレッドのままであるほどです。
これは、いわゆるシングル スレッド エンジンで実行されるスレッドが常に 1 つだけであるという意味ではありません。ただし、重要なタスクはすべて、通常、1 つの中央スレッドで実行されます。衝突検出などの一部のものはマルチスレッド化される可能性がありますが、一般に、Tick の衝突フェーズは、すべてのスレッドが戻り、エンジンが単一の実行スレッドに戻るまでブロックされます。
マルチスレッド化は、コンテナも含めすべてがスレッドセーフでなければならないため、パフォーマンスの問題も含め、非常に多くの問題を引き起こします。また、ゲーム エンジンはそもそも非常に複雑なプログラムであるため、マルチスレッド化によって複雑さが増すほどの価値はほとんどありません。
固定時間ステップアプローチ
最後に、別のコメント投稿者が指摘したように、固定サイズの時間ステップを設定し、ゲーム ロジックを「ステップ」する頻度を制御することも、多くの利点があり、これを処理するための非常に効果的な方法になります。
完全性のためにここにリンクしましたが、他のコメント投稿者もリンクしています:タイムステップを修正する