Can I use multiple timer handles on the same actor?

I currently have this code in a .cpp file:

pawn->GetWorldTimerManager().SetTimer(timerHandle, this, &UClass::TimerCallback, processingTime, false);

This is same code is being called from two different classes, but on the same actor (which I have called ‘pawn’ in this example). The timer handles are initialized in the two classes, with different names, as with the delegate functions. The difference is that this line of code runs fine in one class, but not in the other, despite using the SetTimer() function in the exact same way.

Given a processing time > 0.0f, the first class delays for the proper amount of time before running the correct TimerCallback() function. The second class is given the same processing time, but it doesn’t delay nor run the TimerCallback() function. I’ve stepped through it and I think it could be something to do with the timer handle not being initialized, though I can’t see why because I’ve initialized both timer handles the same way in both classes (actually, neither of them are ‘initialized’, they are simply declared in the .h file and I guess it’s initialized when I call SetTimer()…?).

Anyway, I just want to know why this is happening. Is it a conflict with the timers in the same actor? Or the fact that the delegate functions are from different classes? Or am I not properly using SetTimer, or initializing the Timer Handle properly?

I personally have no idea, but you can just make your own timers too if you don’t get an answer :slight_smile:

Try doing this:

pawn->GetWorldTimerManager().SetTimer(timerHandle,
    FTimerDelegate::CreateLambda([this]() {
        TimerCallback();
    }), processingTime, false
);

Using the above solution should get past the issue with FTimerManager::SetTimer specific overload feature being…

If a timer is already set for this delegate, it will update the current timer to the new parameters and reset its elapsed time to 0.

Instead the code snippet I provided uses the overload of FTimerManager::SetTimer** that gets a generic delegate. This may not be best practice, however.

** The example on this page seems to be incorrect. It doesn’t seem to be actually using the correct overloaded method.

I would think that declaring different handles would be a better solution, e.g.

Header:

FTimerHandle FirstTimerHandle;
FTimerHandle SecondTimerHandle;

Cpp:

AYourClass::SomeFunction()
{
	...
	
	// Start timer on first handle
	GetWorldTimerManager().SetTimer(FirstTimerHandle, this, &AYourClass::FunctionToCallViaFirstHandle, 5.0f);
	
	// Start timer on second handle
	GetWorldTimerManager().SetTimer(SecondTimerHandle, this, &AYourClass::FunctionToCallViaSecondHandle, 1.0f);

	...
}

AYourClass::FunctionToCallViaFirstHandle()
{
	// Do stuff
}

AYourClass::FunctionToCallViaSecondHandle()
{
	// Do stuff
}