The most straightforward way to use timers in C++ is to declare a UFUNCTION
and a FTimerHandle
in your class
1
2
3
4
UFUNCTION()
void HandleTimerExpired();
FTimerHandle MyHandle;
and starting the timer with the registered callback function from anywhere in your code, like so:
1
GetWorld()->GetTimerManager().SetTimer(MyHandle, this, &ThisClass::HandleTimerExpired, Seconds, bLoop);
In a lot of cases the above example is already getting the job done, but there is a big limitation: The specified callback function must be a void function with no input parameters.
So how does one call a function that has input parameters via a timer?
1
2
UFUNCTION()
void HandleTimerExpired(bool bInputFlag, int32 InputValue);
In that case we can create a FTimerDelegate
as UObject-based member function delegate and pass our parameters directly when creating the delegate. In the SetTimer
call we now use our FTimerDelegate
:
1
2
3
FTimerDelegate MyDelegate = FTimerDelegate::CreateUObject(this, &ThisClass::HandleTimerExpired, true, 10);
GetWorld()->GetTimerManager().SetTimer(MyHandle, MyDelegate, Seconds, bLoop);
So far so good. That still leaves the question of how to call a function with return type via timer?
1
2
UFUNCTION()
bool TryHandleTimerExpired();
FTimerDelegate
doesn’t allow a return type, but we can work around this limitation with the help of a lambda. The general syntax for lambda functions in C++ follows the pattern [ captures ] ( params ) { body }
—check cpp reference to learn more.
Here is a simple example of creating a FTimerDelegate
from a lambda function that wraps our callback function:
1
2
3
4
5
6
7
8
9
10
FTimerDelegate MyDelegate = FTimerDelegate::CreateLambda( [this] ()
{
if (TryHandleTimerExpired())
{
// Do even more stuff if function returns true.
}
});
GetWorld()->GetTimerManager().SetTimer(MyHandle, MyDelegate, Seconds, bLoop);
There are even more ways to create a FTimerDelegate
but those three simple examples are covering the most common use cases already.
Don’t forget to clear your timer handle during EndPlay
to not leave any timers running if the object gets destroyed:
1
GetWorld()->GetTimerManager().ClearTimer(MyHandle);