Multiple timers vs one event tick

I am creating economy system to my game and I am wondering what solution could be more efficient.

So in my system each job logic is run in seperate Object blueprints. Above them all is Economy Controller. Each job takes certain amount of time. One solution to count this time is to create timer, in this Object, which fires event/function after certain amount of time.

Another soultion to this problem would be to create event tick in for example Economy controller and than send info to each job how much time has elapsed, than each Job would calculate elapsed time and go on from there.

I am wondering which solution could be better if my system would run for example 100 jobs. So my question is which solution is better? Or maybe you have a better solution?

It seems like one timer running versus many would be generally more efficient. I only have layperson understanding of computer science, but I think that iterating over an array will be faster than finding disparate objects in level and iterating for each.

Economy controller can just constantly run a timer and when new jobs are created, an event assigns them an int that can be incremented from the timers (or decremented, whichever made more sense).

So the data would be something like a map where you have object reference for the job, and an int to measure how long is has been going on. But the jobs themselves dont have to run timers or watch anything on tick.

I can’t for sure say this is better, just adding it as alternate idea.

hi @tomaszewski5252

is this turn based? or is it running in the background all the time?

if its turn based you wouldnt have to set a timer just run each event in order and wait for them to finish or raise an event for the next task.

if this is to run every x minutes or seconds in the game, then only 1 timer is needed. Set the time to the amount of time for the first update. Each task run when they receive a completed event from the task before. after the final task, reset your timer.

now if this is inside a blueprint it will run async from the main game and control itself, you would need to know how long a task takes as it wont start til triggered by previous task finishing. maybe an enum state that each task waits for as an alternative?

I think timers in unreal are still referenced by string, which leads to total mayhem in bigger code.

Clean solution for such system:

  • make parent class blueprint that holds all communication, and creates your own “my_tick”
  • create dispatcher somewhere like game mode, hook to it from that parent class blueprint, trigger that dispatcher when game does my_tick (like every second or 25ms etc, not per frame)

Now you have your own easy to code and maintain timer. Every blueprint actor that needs it should be child class of that parent one. You can also use “Blueprintable components” for this.

Then you need logic for child actors. Easiest would be sending longinteger value for each my_tick, and increment int every my_tick. If you trigger it once a second it would take almost 70 years to flip that counter.

So for eg if you need to trigger something every 5th my_tick, you store delta value as variable, then update when last tick that was executed happened, and wait until current integer number for ticks is greater than last tick that happened plus delta:

if current tick > last tick + delta:
{last tick = current tick
then do whatever }

You can alo use modulo operand, for every 5th my_tick, do integer counter modulo 5 and check if result is 0. This modulo is also great if you have some action that is heavy to calculate. You do modulo 5, then each actor that needs to operate in same group checks if modulo result is 1,2,3,4 or 5 and you have your group of heavy calculations per actor split into 5. They all work at same speed, and you exacute 1/5th of that group every tick. And you can add more without worrying, just give them 1 to 5 number (or even random int in range)

1 Like

Your second solution is essentially how timers work internally in the engine.
All timers from all actors are contained within the world’s TimerManager singleton, which counts them down every Tick, and triggers them when they reach zero.

If you make a single class that uses Tick to trigger timer callbacks for all the other classes, then you are basically redoing the same thing the engine does, but probably in a less efficient manner.

2 Likes

I know that, however for me deal-breaker with timers is (or was some time ago) referencing them by string. So usually I make my own purely BP timer system (for projects that are BP only).

timers come with a handle that you can reference. But I’d prefer not to have one class look at the specifics of another, and instead just send out an event and then the economy controller would listen. This way there isn’t confusion about who is poking in whose business. If we want to be certain about every thing happening in regards to timers, we simply look at list of bound events in the economy controller (for example)

Thank you for your answers, a lot of insteresting ideas. . Right know I am testing an aproach using multiple timers, mainly beacause of what I have heard from @Chatouille about how timer works. But the aproaches using one tick that sends elapsed time to jobs or Map of jobs with amount of time to finish also sound promising