SetTimer by Eventについて
指定時間の経過後に処理を呼び出せる便利なノードです。
こういったLatentノードではDelayなんかをよく使うと思います。
SetTimer系の便利なとこはループさせたり
任意のタイミングでループを終了させたりできることですね。
似た関数でSet Timer by Function Nameというのがあります。
今回はこちらの解説は端折ります。
個人的に関数名を文字列で渡したりするのはあんまり好きではないですね。
FTimerManagerについて
こういったタイマー系の処理は素直にC++で組むと結構面倒です。
ですが、Unreal C++は色々と便利な関数を用意してくれています。
先ずはSetTimer関数を呼び出すためにFTimerManagerを取得します。
TimerManagerはWorldが保持しており、このように取得できます。
FTimerManager& timerManager = GetWorld()->GetTimerManager();
また、Actorを継承したクラスであれば下記のように取得できます。
FTimerManager& timerManager = GetWorldTimerManager();
SetTimerについて
TimerManagerの中にSetTimer関数があるのでこちらを使用します。
今回は例としてActorからの呼び出しを行っています。
FTimerHandle handle;
GetWorldTimerManager().SetTimer(handle, this, , , );
簡単な例として0.2秒後にLogを出す処理を書いてみます。
void AExampleActor::BeginPlay()
{
Super::BeginPlay();
FTimerHandle handle;
GetWorldTimerManager().SetTimer(handle, this, &AExampleActor::OutputLog, 0.2f, false);
}
void AExampleActor::OutputLog()
{
UE_LOG(LogTemp, Log, TEXT("Call SetTimer"));
}
また、SetTimerはいくつか種類があり、ラムダ式を使用することもできるため
簡単な処理であれば直接書いてしまってもいいかもしれません。
この場合は引数としてthisポインタを渡しておらず、引数が違う点に注意です。
void AExampleActor::BeginPlay()
{
Super::BeginPlay();
FTimerHandle handle;
GetWorldTimerManager().SetTimer(handle, []()
{
UE_LOG(LogTemp, Error, TEXT("Log message"));
} , 0.2f, false
);
}
タイマーの停止、再開について
処理をループさせている場合のタイマーの停止、再開は下記のように行います。
FTimerHandle handle;
FTimerManager& timerManager = GetWorldTimerManager();
timerManager.PauseTimer(handle);
timerManager.UnPauseTimer(handle);
これで任意のタイミングでタイマーを操作できます。
タイマーの終了処理について
タイマーを使用した場合は終了処理も合わせて書くようにしましょう。
void AExampleActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
Super::EndPlay(EndPlayReason);
FTimerManager& timerManager = GetWorldTimerManager();
timerManager.ClearTimer(handle);
timerManager.ClearAllTimersForObject(this);
}
引数付きの関数を渡す場合について
関数にパラメーターを渡す場合はFTimerDelegateのBindUFunctionを使用します。
このBindUFunctionを使用する場合はUFUNCTIONマクロがないとエラーになるので注意です。
UFUNCTIONの説明の際に軽く触れています。
UE4 UFUNCTIONの種類について - PaperSloth’s diary
UFUNCTION()
void InitializeTransform(const int32 Id, const FVector& Location, const FQuat& Quat);
void AExampleActor::InitializeTransform(const int32 Id, const FVector& Location, const FQuat& Quat)
{
UE_LOG(LogTemp, Error, TEXT("Call InitializeTransform"));
}
FTimerHandle handle;
FTimerManager& TimerManager = GetWorldTimerManager();
FTimerDelegate TimerDelegate;
TimerDelegate.BindUFunction(this, FName("InitializeTransform"), 100, FVector::ZeroVector, FQuat::Identity);
TimerManager.SetTimer(handle, TimerDelegate, 1.0f, false);
BindUFunctionは文字列で関数名を渡すため、関数名や引数を変更する際は漏れが発生しやすく注意が必要です。