Skip to content

Instantly share code, notes, and snippets.

@Anuken
Created June 26, 2026 15:25
Show Gist options
  • Select an option

  • Save Anuken/987b66dedc956033fd083f80e6e01445 to your computer and use it in GitHub Desktop.

Select an option

Save Anuken/987b66dedc956033fd083f80e6e01445 to your computer and use it in GitHub Desktop.
Fixed Timestep in Mindustry

Fixed Timestep Overview

What does 'fixed timestep' even mean?

Currently, Mindustry runs building logic at the same rate as the game updates. If your game is running at 1000 FPS, blocks update 1000 times a second. If you're running at 60 FPS, they update 60 times, etc.

In order to compensate for the vast range of potential FPS values, blocks currently use delta time - the time between updates (frames in this case) - to scale values. For example, a conveyor must move items a certain distance each update. In theory, multiplying this movement distance by the delta time means that items move at the same (real world) speed, regardless of whether you are doing 1 or 100 updates a second.

The issue with this approach is that using delta time is not accurate. Updating a block twice at 60 FPS (1x delta) often gives different results than updating the same block once at 30 FPS (2x delta). There are many examples of this kind of behavior across different blocks, and it's impossible to complete eliminate using this method.

In contrast, a fixed timestep would run block logic a fixed number of times per second - 30, for example. As long as your device is capable of running the simulation at that rate, it would always run blocks the same way, regardless of how high your device's FPS is. There is no inconsistency. If it cannot run everything at 30 updates for second, it just runs fewer updates, meaning that the game will visually slow down.

Fixed timestep is an extremely basic concept that is standard across game engines - usually for things like physics simulations. Frankly, Mindustry should have been using it day one, but we're a long way past that now.

Advantages

Consistency

Many different blocks - most prominently, liquid transport blocks - have different throughputs depending on FPS. Some are fairly stable, and some have significant falloff as the user's framerate drops. This means that the efficiency of a given schematic isn't necessarily constant; it depends on how well the game is running. Even outside of schematics, some setups can just stop working because the FPS dropped. For a game focused around efficiency, this is a significant problem.

With a fixed timestep, this problem doesn't exist anymore. Blocks are always simulated the same way every update.

Performance

If your device was running anywhere above 30 FPS, fixed timestep will be a significant 'optimization' to building logic. Instead of having to do 60 updates a second to reach 60 FPS, the game only has to do about half as much. This makes it far easier to reach 60+ FPS, assuming block updates are the bottleneck.

Disadvantages

Interpolation

When block logic runs at 30 updates per second and the game runs at 60 FPS, the visuals of most blocks get noticeably choppy. To fix this, the states of blocks are interpolated between updates. For most blocks, this is easy to implement. For conveyors, it is not.

Mods would also have to implement interpolation for any custom block types they have, assuming they care about choppy visuals. How much work will be needed depends on the type of block.

Slowdown

Some servers often run at TPS values well below 30. If fixed timestep is implemented, there would be significant slowdown in such cases - a server running at 10 TPS would be running at 1/3 game speed.

I don't think 10TPS servers were very playable to begin with, but this arguably makes it worse.

Throughput changes

Running blocks at a guaranteed 30/s instead of the 'normal' 60/s will inevitably make some behave differently. In the current latest stable release, some blocks (most notably, conveyors) have noticeably lower throughput at 30FPS. This has the potential to break schematics.

With a little bit of effort, however, most of these problems can be fixed without breaking anything. The issue with overdriven conveyor throughput, for example, has already been solved. I haven't done tests with many other block types, but it's unlikely to pose a major issue. At worst, base throughput of some blocks can simply be increased to compensate for the change.

Q & A

Why not just increase the floor of the current delta to 30FPS?

This is not equivalent, for several reasons:

  • It doesn't actually make behavior consistent, because you still have the whole [30, +infinity] range of framerates to update the blocks at.
  • If your game is running below 30 FPS and blocks are not the bottleneck, you are still forcing block updates to slow down. Fixed update doesn't have this problem; multiple block updates can happen per frame.
  • It has no performance benefit, which is admittedly a minor point.

Why 30 updates per second?

Many devices can't reach 60 consistently, and at values below 30, the simulation tends to break down.

What about units?

Units generally don't have major significant behavior changes at varying FPS values, and interpolating them is very annoying, so they are unlikely to use a similar fixed update system.

When blocks slow down, they should slow down as well to match, although this has not yet been implemented.

Will my schematics break?

Probably not, see 'throughput changes' above.

Is this actually going to be implemented?

Frankly, I don't know. This is a significant change that requires a lot of extra work to finalize, and at the end of the day, most people don't care, and I don't blame them. Players want to see content, not boring technical changes. I'm not sure if it's even worth it myself.

For now, you can compile it yourself and see how things function in the fixed-timestep branch. Yes, you have to compile it yourself; this is for technical users only.

This feature will likely be sitting in another branch for a while, until I see how other people feel about it as a concept.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment