Determinism is a subject that gets talked about a lot in various threads, but I haven’t seen a central location to discuss it so thought I’d make one. (N.B. I’m not an expert in software determinism, just interested in its uses for netcode. If there are any errors in the below please feel free to correct me.)
Tl;dr, some questions about determinism in Unity
- Is cross platform float determinism in all code (not just Burst) feasible as a feature Unity could investigate (either through IL2CPP or other means)? Does Unity control the entire toolchain with IL2CPP (to be able to enable strict modes etc)?
- Are there any ongoing efforts/investigations into determinism/deterministic games frameworks at Unity?
…but what is determinism, and why does it matter?
Overview
In the context of software and specifically games, determinism means that, for a given set of inputs a simulation will always give the exact same outputs. For games applications where determinism is needed it is essential that the outputs are identical down to the individual bit—“close enough” is not enough.
In games, determinism is most valuable for networking. Without determinism, in a standard server-client setup servers must a) simulate the game and b) send the resulting state of the simulation to all clients.
With determinism, servers do not need necessarily need run the simulation at all (though they still may), and to replicate the state of the game they need to only send the clients’ inputs. This is since if every client receives the same input set and inserts them into the simulation in the same order, all clients will end up with the exact same simulation. This means that bandwidth scales only with player count and input size, rather than with overall game state.
In terms of genres determinism is mostly widely used for RTS (allowing games like StarCraft in 1998 to support hundreds of units in a single match) and fighting games, but general purpose cross platform engines like Photon Quantum show that this paradigm can be used for a wide variety of genres.
Deterministic Math
The first consideration for making a deterministic game is ensuring that your basic math operations are all deterministic. This can be challenging if you are looking for cross platform play (e.g., PC (x64) and Android (ARM) playing matches together) and using floating point arithmetic. Based on my research it seems that it is achievable with a few conditions. IEEE 754 required arithmetic operations seem to be deterministic cross platform for modern consumer hardware (xoofx notes here than ARMv7 has inconsistencies with subnormals). Non conforming operations like trig would need to be implemented in software. An example of this approach can be seen in the Rust physics engine Rapier, which advertises cross platform determinism. Rust using LLVM also makes this easier.
I also made a small repo to test cross platform float determinism, comparing arithmetic done in C# with calls to a native binary (made using Rust.) Tested what I think (?) are the main edge cases, actually found no desyncs between PC and Android (other than some NaN orderings, some comments in the README about that).
Deterministic floats test repo.
It might be challenging for Unity to guarantee cross platform float determinism with Mono builds, since .NET may have some issues with float determinism. IL2CPP would be another option, since I assume with it Unity controls the entire pipeline there, so maybe a feasible problem?
More narrowly Burst compiler was initially advertised as looking to offer cross platform determinism, but from [the latest news it looks like that feature is on hold]( DOTS Development Status And Next Milestones - December 2021 page-2#post-7727097).
An alternative to floats for determinism is fixed point math. Fixed point math uses integers with a fixed radix point to emulate real numbers, performing arithmetic in software. Performance for arithmetic can be quite good with setups like 48.16 (48 bits for the integer part, 16 for the fraction). Drawbacks with fixed point are precision issues that floats do not run into, and needing to rewrite any existing libraries that use floats.
Fixed Point Sharp, C# 48.16 fixed point math library
Deterministic Game Framework
Once your basic operations are all deterministic, the next step is to ensure that every other action in your game is deterministic. The best way to manage this is to be able to exactly compare the game state on one device to the game state on another to be able to immediately detect divergences every tick. This usually means building a checksum by iterating over every piece of data used for gameplay and sending it between clients. There’s lots of little gotchas for determinism (.NET’s dictionary iteration is non-deterministic, tying any logic to the variable update loop), so being able to detect desyncs immediately makes it a tractable problem.
It can be a lot of work to build a deterministic framework (none of the MonoBehaviour workflow is written to be deterministic), but providing basic math operations are deterministic this is something that can be done by the Unity community.
Unity DOTS Physics
Unity DOTS Physics is apparently deterministic, which is pretty neat. It’s also stateless, making it ideal for rollback networking. Although it has a bunch of ECS authoring and runtime tools, it’s actually entirely decoupled from ECS. I wrote a prototype game object wrapper for it, since it seems like a really strong tool, and being accessible to MonoBehaviour projects would make it more widely used.
Link to thread about DOTS Physics with Game Objects
Probably took a lot of effort to ensure it was deterministic, so having cross platform float determinism would heavily increase its offering (as would giving the engine a proper name lol).
Hope this has provided a good idea of what determinism is and its applications. Interested to know others’ thoughts (and any corrections to the above!) and areas of interest on the subject. (Pinging @GabrieleUnity @Joachim_Ante_1 and @xoofx since I think you have all looked into deterministic floats with Burst, thought this might be of interest. @TheOtherMonarch I know you were also interested in this subject in the DOTS thread too.)