I'm writing a game, where a player controls a spaceship.
It regenerates energy over time. So I need to make a little timer that adds certain amount of energy to the pool per second.
My enemies also shoot at me, activate different abilities. I figured I can use separate timers for these too.
But I see how this can quickly go out of hand, since I have different engines with different energy regeneration rates - will I need to replace the timer every time?
Or if I have different energy - I have to manually track all the timers and set them anew.

I thought, maybe I can use some global singleton method that can handle all the timing in my game? It can update everything in the game, and when something new happens (like new enemy spawning) I can just send my singleton information about that object and it will handle all the timing for it?

Is this a good approach? Can I read up something about this somewhere?
Maybe you have some experience with this?

4 Answers
4

Given the options in your question, separate timers would be the best approach.

I'm not sure what your implementation of the "timers" is but you can get a major performance increase and simplify things by using a different approach. Rather than using timers (as in stop-watch type timing) you could use time stamps that represent the expiration of a cooldown and to determine if the cd has expired, you would check against the time from the physics engine during physics engine ticks or update calls. This way you aren't managing a whole bunch of individual timers and are simply maintaining a series of time values to represent the timer end times.

Many individual timers can cause race conditions. Set one timer to 50 ms, 10 ms later set another timer to 40 ms. Which one will fire first? Often there is no way of knowing, and the result may be different from one run to another due to minor performance variations. Often it is not an issue, but bugs caused by race conditions can be really hard to track.

The most reliable way of keeping time is to hang everything in your game on the same update rate, then measure all other timing relative to that update rate, and have a well defined order in which events are handled when they fall in the same "tick". Performance variations may still cause small deviations from that update rate, but as it affect everything equally the order of events remain the same.

For instance you may choose to run 120 updates per second, if you want a ship to move 10 km/s you would give it a speed of 83 metres per update, and if you would like a ship to fire every 1.5 seconds you would make it fire every 180ᵗʰ update.

You can loop through every object on every update and decrease their respective timers, even a phone is too fast for that approach to cause any performance issues.

It seems you're spending too much of your mental and motivational resources attempting to circumvent a problem that will likely never realize. Are you planning on having 10's or 100's of thousands of timers simultaneously? Or will it be a handful of timers for a handful of entities?

If the latter, which would be nearly certainly the case for the vast majority of games, whatever method you use (as long as it's effective) is fine. Specifically, individual timers is good enough. Don't optimize for any process before you encounter a problem unless you know (likely from experience) that you'll have performance issues.

Remember that your internal resources, that you spend to create the game, are just as or far more valuable than system resources. The time you spend solving non-problems is more of a concern than unknown or very small performance gains.

I have chosen to go the few timers route but I have already faced problem - sometimes I need to pause all of them, and gathering all pointers to all timers from different timers in one place can be problematic. This is how design decision impacts me.
–
DvoleMay 13 '13 at 7:30

You should be handling everything in the Update methods. Whether you're using timers that are cycle-based, or ms-based using deltaTime, or whatever everything should be happening in update(); An entity's update() is where you handle anything and everything outside of rendering, so stopping the game from updating those entities will, by default, stop timers (assuming you aren't using timers based only on System-time). If the problem is that you're using System time, independent of update(), simply use deltaTime inside of update() instead.
–
AttackfarmMay 13 '13 at 18:13

I use separate method that calls certain method every second or so.
–
DvoleMay 13 '13 at 20:04

I would say, that you could use a single timer for all of these. If I don't recall wrong, Minecraft uses a system very similiar to this. Everything that needs a cooldown(Like redstone), uses "ticks". Every second is composed of 20 ticks. The game checks for the number of ticks to calculate timing.

Applied to your situation would be like this:
You could have a single global timer that fires a specific times a second(20 times in above example). And for every tick, you could add an engine-specific amount to energy pool.
For example, a basic engine adds 1 energy for each tick, while a HYPER-ULTRA-OVERCLOCKED engine adds 999 energy each tick. Hope this helps.