the problem aren’t the ticks. the problem is the amount and type of work that you do.
and also how well grouped it is (e.g. having the pawn ticking to do something weird on other actor it’s a bad sign). as well as not ticking when not necessary. which basically is not doing work you don’t need (which is a basic optimization idea).
i like timers and i use them often, but usually for simple things, one off things.
for recurring things i use tick.
the benefit of ticks is that you can control them like:
- changing the interval
- pausing
- choosing to not pause them on game pause
- enable/disable ticking when you want.
- choosing WHEN to perform the work (pre physics, during, etc.)
- running async (in another thread) with bRunOnAnyThread and the cvar
tick.AllowAsyncComponentTicks
- batching and doing the work in parallel (there are some optimizations for this on 5.x with some cvars (i’ve been experimenting with this)).
-
- tick.AllowBatchedTick and tick.AllowConcurrentTickQueue among MANY others tick.AllowConcurrentTickQueue | UE Setting & Cvar Wiki
- prerequisites for ticking (ensuring ticking order among many elements)
- Integrates better with the engine. for example the plugin i’ve shared works well with tick intervals out of the box. You can add custom behavior to control your timer but it’s extra code.
-
- Being tick a base functionality of the engine, it also easily generalizes to other classes, plugins, objects, etc. You can easily check for Actor->IsActorTickEnabled without having to cast. That not only is a tiny bit faster, but also reduces the problem of dependencies (which is a real issue in blueprints).
-
- debug tools, visualization, profilers, logs, etc. that timers don’t have.
for this, i think, ticking architecture is far superior to hand made timers when it makes sense. otherwise you’re simply overcomplicating.
i’ve made a plugin to handle significance jerobarraco/JSig: Plugin to handle significance very easily on unreal engine 5 - Codeberg.org
which allows you to control tick intervals (among several other things), based on things like occlusion, distance, visibility (and other stuff).
you would need extra code to implement this with timers.
what i do to ensure the tick code is as optimal as possible (in general terms) is
- try to keep the code grouped where it needs to. (separation of concerns some ppl call it).
that means, i tend to have components that tick and group the data and logic together (which could further increase data locality on the cpu)). (e.g. i have a component that performs some animation, it has its own tick and data) - avoid doing what i don’t need to. cache data. (e.g. instead of using GetActorOfClass every tick, i cache that in a variable).
which are things that could help you in any way you implement it (ticks or timers).