Software engineering of video games and other abstract simulations demands concise modelling, and chief among the things needing modelled is the passage of time. In much the same way the universe itself is understood to be ultimately discrete, so too must our simulations follow a common denominator for the passage of time.
Types of ticks
Depending on what kind of process is being accommodated with this time, smaller or larger units may be needed — these are called ticks. There are three main sizes of ticks:
large ticks, clocking in at 600 milliseconds
medium ticks, clocking in at 60 milliseconds
small ticks, clocking in at 6 milliseconds
Small ticks
Nominal length: 6ms
Small ticks are best suited for machine-local applications like locally-instanced simulations and single-player video games. They provide ample time for any modern processor and video card pair to perform all of the business logic and rendering computations necessary to display the next logical frame (more on the ‘logical’ part later).
Medium ticks
Nominal length: 60ms
Medium ticks are best suited for intense simulations that a user can adjust the speed of, as well as more demanding networked video games like real-time strategy games. Sixty milliseconds provides the tightest feedback loop possible on a high quality internet connection for the most active user experiences, while still being large enough to cope with the realities of input lag and subpar connection quality.
Large ticks
Nominal length: 600ms
Finally, large ticks are ideal for massively-multiplayer video games and other globally networked simulations that may involve users numbering into the thousands connecting from all over the world. Not coincidentally, six hundred milliseconds is the nominal tick rate of the Old School RuneScape clock, which serves the very same purpose as the ticks described here.
The purpose of ticks
Like object models facilitating object-oriented programming techniques, ticks provide a hard abstraction for application developers to model their work on top of. Once a tick size is chosen, it is regarded as the smallest possible unit of time that can be distinguished freely by the application; smaller quantities of real time are exclusive to the domain of the underlying engine and cannot be introspected upon. Setting this lower limit makes it practical for the application to maintain temporal coherency in a fully generalised way.
The nature of ticks
It is crucial to understand that ticks are an application modelling substrate – they are an abstract premise upon which to base one’s work, not a concrete reflection of the reality of the application in motion, nor even an attempt to reflect that reality. One consequence of this is explained succinctly on the wiki link above:
An action taken during one tick can only happen, at the soonest, at the beginning of the next tick. This can cause your action to be carried out instantaneously, or after a delay of nearly 0.6 seconds, depending on how long you had to wait until the next tick.
Another consequence is that the true lengths of ticks will be variable – the engines underlying one’s application need only to strive for the nominal length, not meet it. A good rule of thumb is to expect a ±5% continuous margin of flux in either direction from the nominal length – for large ticks, this makes a range of 570 to 630 milliseconds. Except for momentary spikes, larger sustained values implies the engine is broken or poorly architected.
One more very important thing to remember is that ticks are for application modelling. Do not confuse it as being a floor for rendering frames or other fundamental engineering tasks, as those can (and almost always should) be totally decoupled in timing from the rest of the engine. For example, a video game may use small ticks of 6 milliseconds, but it can render 60 frames per second, or even 360 frames per second, despite the nominal length of small ticks correlating to 166 ⅔ frames per second.
Bonus: tiny ticks
Nominal length: 600µs
(0.6ms
)
This one was added in to accommodate real-time graphical user experiences. Unless you have a monitor from the future that can display in excess of 1,600 Hz and the definitively superhuman vision necessary to perceive and enjoy it, this unit of time is going to make a round trip of logic happen faster than the visual result can be delivered to you, always.
This might seem like a short amount of time even for a processor, so let us contextualise it into an imagined (and very basic) RISC machine that gets 1 instruction per clock cycle.
At 10 MHz, there are 6,000 instructions to be run in 600µs
At 100 MHz, there are 60,000 instructions
At 600 MHz, there are 360,000 instructions
And at 3 GHz, there are 1,800,000 instructions
And this is just for a central processor. Remember that thanks to decades of innovation in microarchitecture design, many processor designs can, in the right conditions, well exceed 1 instruction-per-clock. This is possible through caching, branch prediction and occasionally the so-called SIMD instructions depending on their applicability. Furthermore, there is often a dedicated multi-processor chip available to be used for video rendering, which also adds to the processing budget for a 600µs slice of time.
Wrapping up
Thank you for reading. If you found this article helpful, please be sure to share it with someone you know who may also find it useful. Consider subscribing as well to catch future writings of mine. Thanks again!