N秒ごとに何かが発生したいのですが、どうすればよいですか?タイマーを使うかもしれませんが、どうやって?
N秒ごとに何かが発生したいのですが、どうすればよいですか?タイマーを使うかもしれませんが、どうやって?
回答:
これに対する一般的なアプローチは、更新ループとデルタ時間を使用することです。
float timerCurrent = 0f;
float timerTotal = 5f;
Update() {
timerCurrent += deltaTime;
if(timerCurrent >= timerTotal) {
//do timer action
timerCurrent -= timerTotal;
}
}
これは、deltaTime
変数にアクセスできることを前提としています。デルタ時間は、最後のフレームから経過した時間です。多くのエンジンでこれを利用できますが、独自のエンジンの設定についてはこちらをご覧ください。
ほとんどの言語ではclock.startTimer()
、メインループに入る前に、ある種の関数呼び出しでクロックを開始する必要があります。次に、メインループに入る前に、のような関数を使用して、時刻値を変数に格納する必要がありますtime = clock.getTime()
。ステップ時間を変数に格納しますn
。
あなたのメインループでは、あなたがしたいチェックはの線に沿ったものです
if(time + n <= clock.getTime())
//do stuff
time = clock.getTime() //important to assign new time value here
注:どの言語/ライブラリを見ているのかわからないので、これは頭の中で考えた一般的なアルゴリズムにすぎません。ニーズに正確に適合しない場合があります。一部の言語/ライブラリでは時計オブジェクトを作成する必要がありますが、他の言語/ライブラリでは関数を直接呼び出すだけです。
以下のコメントのとおり、使用している言語に応じてスレッドの問題に注意する必要があります。また、格納するためにダブルフロートを使用する必要がありますtime
。
time
ゲームの経過時間を保存する場合は、倍精度浮動小数点形式を使用する必要があることにも注意してください。
他の回答がすでに指摘したように、タイマーの実装は、格納された値を各フレームのでインクリメントし、deltaTime
それを期待される持続時間と比較することで実行できます。完全を期すために、他の回答と非常によく似たコードを含めます。
float elapsed = 0.0f;
float duration = 4.0f;
void update(float deltaTime) {
elapsed += deltaTime;
if (elapsed <= duration) {
// Run code.
elapsed = 0.0f;
// Maybe remove from update loop?
}
}
扱い方はあなた次第// Run code.
です。多分あなたはTimer
クラスを持っています、そのインスタンスはdelegate
(C#)またはcallback
(C ++)を取り、タイマーが切れたときにそれを呼び出します。また、タイマーを一時停止するには、タイマーを更新ループから削除します。
別のアプローチは、タイマーの開始時間をマークし、代わりに経過時間のオンデマンド計算を行うことです:
double startTime = 0.0; // This is a double for a reason, I'll explain below.
bool running = false;
void start() {
startTime = getTime(); // This is whatever system time call you want to use.
running = true;
}
double getElapsed() {
double elapsed = getTime() - startTime;
return elapsed;
}
このスタイルは、タイマーのユーザーにもう少し制御を与えます。構造自体は、経過時間が特定のポイントに達したときに何をすべきかについては関係ありません。更新さえしていません。ユーザーは、必要なときに経過時間を問い合わせることができます。このパターンには、デバッガーに適さないという残念な副作用があります。プログラムがデバッガーで停止している間、システム時間は継続するため、このようなタイマーはプログラムをステップ実行するときに異なる動作をします。これに対する潜在的な解決策は、システム固有の経過時間を使用してフレームごとに更新されるプログラム固有の経過時間値を維持することです。
特にゲーム開発に関しては、コンピューターでのタイミングの2つの癖が最も重要だと思います。1つ目は浮動小数点精度で、2つ目はネイティブタイマーの解像度です。
2番目の例では、最初の例と同様に、のdouble
代わりにタイプを使用したことに注意してください(タイプ名は、使用float
している言語によって異なります)。これの理由は、2番目の例が合計経過ゲーム時間を格納することです。ゲームを長時間実行し続けると、単精度浮動小数点形式の値は、経過時間を正確に測定するには精度が不十分になり、安定性の問題が発生します。最初の例はfloat
、大きな期間が予想されない限り、タイプを使用して問題ありません。
逆に、予想される更新時間が十分に短い場合、システム時間の取得方法によっては、実際には最初にそれを達成できない場合があります。タイマーは、多くの場合、実行中のOSのタイマー解像度に依存します。たとえば、Windows 7以下のデフォルトのタイマー解像度は15.6ミリ秒です。つまり、タイマーの解像度を変更しない限り、timeGetTime
またはなどの関数を使用して達成できる最低のタイマー精度GetTickCount
は15.6 msです(それに関連する危険もあります)。
少し長くなりましたが、タイマーを実装するときに注意する必要がある重要な事項です。