Download

Tick vs. Timers

I’ve noticed that the general consensus on ticks is to never use them unless you can’t get around it, and to use timers instead. However, my main concern with timers is when you have to constantly start and stop them. I’m guessing that using tick is better than timers in these cases as there may be some performance cost in starting and stopping them.

An example scenario: I want to update the rotation of a character’s mesh to face its velocity. Sometimes the velocity will not change, so the rotation will not change.
Assuming that calculations are semi-expensive and do not just set the mesh’s rotation to the direction of the character’s velocity, would it be better to:

  1. Throw all logic into tick
  2. Throw all logic into tick, but add a check to only perform updates when mesh rotation does not equal the direction of velocity
  3. Start a timer with interval 0.1f whenever the direction of velocity changes, and end the timer when the mesh’s rotation matches velocity

In fact when you register a new Timer, some new UObject is created behind the scenes;
However, you can reuse that Timer again and again, instead of spawning a new one every time…

Tick will run forever (as long owner is still alive), but it’s a better option if owner has short lifespan and the calculations inside Tick aren’t outrageous.

Never do #3.

  • Tick() only runs if you enable it.
  • Setting off a Timer and starting/stopping Tick() is functionally equivalent.
  • The deciding factor is which code is more readable/maintainable.

So my understanding is that timers should be used for burst-based functions that don’t need to always run, such as updating a projectile’s position for a few seconds, while tick should be used for constant actions like updating a player’s mesh to velocity direction. Based on this, I’m assuming using a timer that runs ~1/10 the amount of tick would be a better idea for a constant action where it isn’t imperative that it’s run every tick, such as a map that plots player positions.

Thanks for the input :cool:

It’s worth mentioning that you can change the tick rate of an actor. This is especially useful in classes like gamemode where you most likely won’t be updating things every frame or so.

Question, Cannot find an answer for this any where!

Which of the following would be more efficient on say an **escalator **moving? In this Epic training video to create an excalator he uses tick: https://www.youtube.com/watch?v=aqRUe7pm4Ok
I have watched a few training Videos from Epic that say to never use tick because it is so inefficient. In the comments of one of the videos I asked what you are supposed to use for a line trace if you cannot use tick, but no one responded. I ended up changing my line trace to use Event Timer set to loop at second = .01, would it be better to use an Tick instead of the Event Timer? I changed the Event Timer to .1 but it was too sluggish and had to change it back to .01.

  1. Tick
  2. Event Timer set to loop at second = 1
  3. Event Timer set to loop at second = .1
  4. Event Timer set to loop at second = .01

Tick and event timers work more or less the same and should have the same efficiency. Tick and Timers are not particular inefficient by themselves but it is what you do with them that matters. You should think of ways to avoid constantly doing line traces or make the line trace as efficient as possible (limit the length, don’t use multi-line, limit the trace channel object count etc.).

Functions that are very demanding should be moved to C++ if they don’t perform well enough in Blueprint or you could try to nativize the Blueprint.

What? This is completely wrong.



**FTimerHandle**  MyTimerHandle;
//  UStruct(BlueprintType) * Parent Class:  **UScriptStruct -> UStruct -> UField -> UObject -> UObjectBaseUtility -> UObjectBase**


const **FTimerDelegate** TimerDelegate = FTimerDelegate::**CreateUObject**(this,&UMyClass::MyFunction);
World->GetTimerManager().SetTimer(MyTimerHandle,TimerDelegate,TickRate,true);


Please, explain why “this is completely wrong”.

2 Likes

FTimerHandle is a blueprint struct, so yeah, there’s going to be a UScriptStruct to represent its reflection data - only a single one is ever created at startup.

CreateUObject method on delegates is used to bind a function on another UObject - so that it won’t crash if this object is deleted. It doesn’t create an object.

Sure… the “another UObject” is some magic object that doesn’t exist and is never created; I got it!

It’s used if you want to bind a timer to a function on a UObject you already have, yeah? You can also bind timers to static methods if you want to.

One important thing that should sometimes be considered is that the timer manager is updated each frame, likely before the object you’ve set the timer on has ticked. Can be important for finding syncronisation issues at times.

This function creates a delegate bound to a UObject, which is just a struct. It’s so the delegate is garbage collecter aware.

Hi All,

I’ve recently been trying out a workflow where I’ve avoided placing things in tick by running simulated ticks for certain mechanic states.

The workflow for each mechanic works as follows:

StartMechanic (called from input if criteria such as state is all good)
MechanicSimulatedTick (called once on end of Start Mechanic function, and then calls to self for next frame via SetTimerForNextTick) (once the mechanic is over, it just stops running).

I’ve found that there is a large behaviour difference between the logic when run via tick and run via SetTimerForNextTick.

For instance, my MechanicSimulatedTick sets the actor location each “simulatedTick”. It’s super choppy (despite delta seconds etc being correct).
If I then remove the call to it from start mechanic, and it’s call to self (setTimerForNextTick) and call it from Tick instead (based on state system) - the SetActorLocation runs smoothly, no problems.

Why might this be the case? Surely they’re both being run on tick. Is it a tick group error for the actor? I know timers are invoked before most of the updates, and by default an actor is ticked PrePhysics.

UPDATE: Looks like the issue might be that timers are invoked between PostPhysics and PostUpdateWork. This would mean that all my movement of the character during that invoked function is running after physics has already run

Seems like there should really be an option to specify when a SetTimer is run (choosing a tick group)

nice and useful article for me and for many others.

GetWorld()->GetTimerManager().SetTimer(MYHANDLE, this, &UMYCLASS::MYFUNC, 0.05f, true);

If we are reviving necro posts, I’d like to add that Lambdas are criminally underrated. Basically, they allow you to write a function inside another function.

// example variables that are outside the lambda
FString MyString = TEXT("blabla");
int32 MyInt = 100;

// creating the lambda timer delegate
FTimerDelegate MyTimerDelegate = FTimerDelegate::CreateLambda([MyString, MyInt]()
{
	// code here...
	
	// if you want to use variables that are outside the lambda, make sure to include them in the [].
	// otherwise, you'll get a compile error.
	UE_LOG(LogTemp, Display, TEXT("MyString = %s"), *MyString);
	UE_LOG(LogTemp, Display, TEXT("MyInt = %d"), MyInt);
});

// binding the timer
GetWorld()->GetTimerManager().SetTimer(MyTimerHandle, MyTimerDelegate, 1.0, true);