Language:
Page Info
Skill Level:
Engine Version:

ゲームプレイ タイマー

タイマー は、アクションを遅らせる、もしくはある期間に渡って発生させる際に使用します。プレイヤーがパワーアップ アイテムを取得した 10 秒後に、無敵キャラクターとなり、10秒後に弱くなる例が挙げられます。プレイヤーが毒ガスで充満した部屋に入ると、 1 秒おきにダメージを与える例もあります。これらはタイマーを使用して実現します。

タイマーの管理

タイマーは、グローバル Timer Manager ( FTimerManager 型) で管理されます。グローバル Timer Manager は、Game Instance オブジェクトと各 World に存在します。Timer Manager を使ってタイマーをセットアップするために使用する主な 2 つの関数があります。SetTimerSetTimerForNextTick です。それぞれ、いくつかのオーバーロードがあります。それぞれどのようなオブジェクトや関数のデリゲートにもアタッチ可能であり、SetTimer は必要に応じて定期的間隔でリピートすることができます。こうした関数の詳細は、 TimerManager API ページ をご覧ください。

タイマーの時刻になる前に、アクタなどタイマーを呼び出そうとしていたオブジェクトが破棄されると、タイマーは自動的にキャンセルされます。この場合、Timer Handle は無効になり、この関数は呼び出されません。

Timer Manager へのアクセスは、GetWorldTimerManager というAActor 関数を通して行われ、これは、UWorldGetTimerManager 関数を呼び出します。グローバル Timer Manager にアクセスするには、UGameInstance 関数、`GetTimerManager' を使用します。これは、何らかの理由でワールドに独自の Timer Manager がない場合に使われるフォールバックでもあり、特定のワールドの存在に関係なく、または依存せずに関数呼び出しをするために使用することができます。

タイマーは、標準の C++ 関数ポインタ、TFunction Objects , または デリゲート と合わせて使用することができます。

タイマーの設定とクリア

FTimerManagerSetTimer 関数は、関数または遅延後にデリゲートを呼び出すようにタイマーを設定し、その関数呼び出しを無制限に繰り返すように設定することができます。この関数は、Timer Handle (FTimerHandle 型) に書き込み、これを使ってカウントダウンを一時停止 (再開)、または残り時間の長さを変更したり、タイマーを完全にキャンセルすることもできます。この関数を呼び出すために使われた Timer Handle の再利用も含めて、タイマーによって呼び出される関数内でタイマーを設定すると安全です。使用例としては、スポーン前だが間もなくスポーン予定の別のアクタに依存するアクタの初期化を遅延させるというものがあります。従属するアクタの初期化関数はタイマーを例えば 1 秒後などの決まった時間の長さで再度呼び出すように設定することができます。または、成功すると自らをクリアするループするタイマーによって初期化関数を呼び出すこともできます。

タイマーは、指定間隔で作動させる代わりに、次のフレームで実行するように設定することもできます。これは SetTimerForNextTick を呼び出すことで実現できますが、この関数は Timer Handle に書き込みません。

Timer をクリアするには、SetTimer の呼び出し中に書き込まれた FTimerHandleClearTimer という 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. (今から 2 秒後に開始しますが、1 秒毎に RepeatingFunction を呼び出します。) 
    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. (この関数を十分な回数呼び出したら、Timer をクリアします。)
    if (--RepeatingCallsRemaining <= 0)
    {
        GetWorldTimerManager().ClearTimer(MemberTimerHandle);
        // MemberTimerHandle can now be reused for any other Timer. (MemberTimerHandle を他の Timer のために再利用することができます) 
    }
    // Do something here... (ここで何かを行います)
}

SetTimer を 0 以下のレートで呼ぶと、ClearTimer を呼び出すのと同じことになります。

タイマーを一時停止して再開する

FTimerManager 関数では、PauseTimer は Timer Handle を使って 実行している Timer を一時停止します。これにより、Timer が関数呼び出しを実行するのを防ぎますが、経過時間および残り時間は、タイマーの一時停止中は同じ状態のままとなります。UnPauseTimer は一時停止したタイマーの実行を再開させます。

タイマーの情報

Timer Manager はタイマーの管理に加え、レート、経過時間、残り時間などの情報を取得する関数があります。

Is Timer Active

FTimerManagerIsTimerActive 関数は、特定のタイマーが現在アクティブで一時停止されていないことの確認に使用します。

例:

// 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. (この武器の発砲のレートは、ウォームアップに従い変化します。) 現在、発砲を待機していますか? その場合、ショット間の現在の遅延はどれくらいの長さですか? 
GetWorldTimerManager().GetTimerRate(this, &AUTWeapon::RefireCheckTimer);

GetTimerElapsed&Remaining 関数

FTimermanager は、与えられた Timer Handle に関連したタイマーに対して、GetTimerElapsedGetTimerRemaining を通してそれぞれ経過時間と残り時間を示します。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. ( -1 が戻されれば、準備が整っています。) 
GetWorldTimerManager().GetTimerElapsed(this, &AUTWeapon::RefireCheckTimer);

タイマーの経過時間と残り時間の合計は、タイマーのレートと同じでなくてはいけません。

既知の問題

  • 現状のコードはスレッドセーフではありません。ゲーム スレッドの外側でアクセスされるとアサートを生じます。