タイマー は、アクションを遅らせる、もしくはある期間に渡って発生させる際に使用します。プレイヤーがパワーアップ アイテムを取得した 10 秒後に、無敵キャラクターとなり、10秒後に弱くなる例が挙げられます。プレイヤーが毒ガスで充満した部屋に入ると、 1 秒おきにダメージを与える例もあります。これらはタイマーを使用して実現します。
タイマーの管理
タイマーは、グローバル Timer Manager ( FTimerManager
型) で管理されます。グローバル Timer Manager は、Game Instance オブジェクトと各 World に存在します。Timer Manager を使ってタイマーをセットアップするために使用する主な 2 つの関数があります。SetTimer
と SetTimerForNextTick
です。それぞれ、いくつかのオーバーロードがあります。それぞれどのようなオブジェクトや関数のデリゲートにもアタッチ可能であり、SetTimer
は必要に応じて定期的間隔でリピートすることができます。こうした関数の詳細は、 TimerManager API ページ をご覧ください。
Timer Manager へのアクセスは、GetWorldTimerManager
というAActor
関数を通して行われ、これは、UWorld
で GetTimerManager
関数を呼び出します。グローバル Timer Manager にアクセスするには、UGameInstance
関数、`GetTimerManager' を使用します。これは、何らかの理由でワールドに独自の Timer Manager がない場合に使われるフォールバックでもあり、特定のワールドの存在に関係なく、または依存せずに関数呼び出しをするために使用することができます。
タイマーは、標準の C++ 関数ポインタ、TFunction
Objects, または デリゲート と合わせて使用することができます。
タイマーの設定とクリア
FTimerManager
の SetTimer
関数は、関数または遅延後にデリゲートを呼び出すようにタイマーを設定し、その関数呼び出しを無制限に繰り返すように設定することができます。この関数は、Timer Handle (FTimerHandle
型) に書き込み、これを使ってカウントダウンを一時停止 (再開)、または残り時間の長さを変更したり、タイマーを完全にキャンセルすることもできます。この関数を呼び出すために使われた Timer Handle の再利用も含めて、タイマーによって呼び出される関数内でタイマーを設定すると安全です。使用例としては、スポーン前だが間もなくスポーン予定の別のアクタに依存するアクタの初期化を遅延させるというものがあります。従属するアクタの初期化関数はタイマーを例えば 1 秒後などの決まった時間の長さで再度呼び出すように設定することができます。または、成功すると自らをクリアするループするタイマーによって初期化関数を呼び出すこともできます。
タイマーは、指定間隔で作動させる代わりに、次のフレームで実行するように設定することもできます。これは SetTimerForNextTick
を呼び出すことで実現できますが、この関数は Timer Handle に書き込みません。
Timer をクリアするには、SetTimer
の呼び出し中に書き込まれた FTimerHandle
を ClearTimer
という FTimerManager
関数に渡します。この時点で Timer Handle は無効になり、新しい Timer を管理するために再利用することができます。既存の Timer Handle で SetTimer
を呼び出すと、その Timer Handle によって参照される Timer がクリアされて、新しいものと置き換えられます。
最後に特定のオブジェクトに関連付けられているすべての Timer は、ClearAllTimersForObject
を呼び出すことによってクリアすることができます。
例:
void AMyActor::BeginPlay()
{
Super::BeginPlay();
// Call RepeatingFunction once per second, starting two seconds from now.
GetWorldTimerManager().SetTimer(MemberTimerHandle, this, &AMyActor::RepeatingFunction, 1.0f, true, 2.0f);
}
void AMyActor::RepeatingFunction()
{
// Once we've called this function enough times, clear the Timer.
if (--RepeatingCallsRemaining <= 0)
{
GetWorldTimerManager().ClearTimer(MemberTimerHandle);
// MemberTimerHandle can now be reused for any other Timer.
}
// Do something here...
}
SetTimer
を 0 以下のレートで呼ぶと、ClearTimer
を呼び出すのと同じことになります。
タイマーを一時停止して再開する
FTimerManager
関数では、PauseTimer
は Timer Handle を使って 実行している Timer を一時停止します。これにより、Timer が関数呼び出しを実行するのを防ぎますが、経過時間および残り時間は、タイマーの一時停止中は同じ状態のままとなります。UnPauseTimer
は一時停止したタイマーの実行を再開させます。
タイマーの情報
Timer Manager はタイマーの管理に加え、レート、経過時間、残り時間などの情報を取得する関数があります。
Is Timer Active
FTimerManager
の IsTimerActive
関数は、特定のタイマーが現在アクティブで一時停止されていないことの確認に使用します。
例:
// Is this weapon waiting to be able to fire again? (この武器は、再度発砲できるまで待機していますか?)
GetWorldTimerManager().IsTimerActive(this, &AUTWeapon::RefireCheckTimer);
Timer Rate
FTimerManager
には、Timer Handle からタイマーの現在のレート (実行間隔) を取得する GetTimerRate
と呼ばれる関数があります。タイマーのレートは直接変更できませんが、Timer Handle を使って SetTimer
を呼び出して、それをクリアして新しいタイマーを作成することができます。これは、レート以外は全く同じです。GetTimerRate
は、Timer Handle が無効な場合に -1
の値を戻します。
例:
// This weapon's rate of fire changes as it warms up. Is it currently waiting to fire, and if so, how long is the current delay between shots?
GetWorldTimerManager().GetTimerRate(this, &AUTWeapon::RefireCheckTimer);
GetTimerElapsed&Remaining 関数
FTimermanager
は、与えられた Timer Handle に関連したタイマーに対して、GetTimerElapsed
と GetTimerRemaining
を通してそれぞれ経過時間と残り時間を示します。GetTimerRate
と同様に、こうした関数は Timer Handle が無効な場合に、-1
を戻します。
例:
// How long will it be until this weapon is ready to fire again? If the answer comes back as -1, it is ready now.
GetWorldTimerManager().GetTimerElapsed(this, &AUTWeapon::RefireCheckTimer);
タイマーの経過時間と残り時間の合計は、タイマーのレートと同じでなくてはいけません。
既知の問題
- 現状のコードはスレッドセーフではありません。ゲーム スレッドの外側でアクセスされるとアサートを生じます。