- Home /
Deterministic physics options
I have recently been doing work on a physics puzzle game. I quickly discovered if you try to simulate the same identical physics scenario multiple times in Unity, you will get different results, due to both Unity's non-deterministic physics engine and its built-in floating point inaccuracies. In order for this game to work, I need my simulations to be consistent, ideally through a deterministic physics engine. What are my options here?
I have tried DPhysics which didn't work and then moved to TrueSync which, although overkill, was promising but has proved to be filled with limitations and a couple of unavoidable bugs. As such I'm wondering if anyone has any other suggestions on how I could find or achieve a deterministic physics system in Unity. I'm happy to use a paid plugin if any exist.
Thanks!
What exact situations have you encountered where the physics system did not behave deter$$anonymous$$istic?
Answer by Bunny83 · Oct 16, 2017 at 02:14 AM
Unity's physics system is 100% deterministic. At least as far as i can tell.
I've quickly created a test scene where i spawn 4 bouncy spheres at different "fixed update frames" (i added a counter) and applied a random force to them using Random.Range, Of course i set a fix random seed at the start. After 3000 fixed update frames i grab the position, the rotation (as euler angles), the current linear and angular velocity of every object and build a single log string which i log to the console. I printed 9 decimal digits for every component to make sure i get to the end of the floating point accuracy.
I run the simulation 3 times by starting the game in the editor, wait until the log appears in the console, stop the game and just restart it. Now i have 3 log messages in the console. You could compare them by hand and you will notice that every single bit is 100% the same. However there's actually an easier way: Just enable "collapse" on the console window. This will collapse all identical messages into a single one. All of my 3 logs got collapsed into one, so they are identical,
The simulation involves many collisions with the 4 tilted border walls as well as collisions between the 4 spheres. I even removed the random forces and don't applied any forces. I just spawned the 4 spheres at the center and let the solver split them. I still get the same result if i run it multiple times.
If it doesn't work for you, you most likely have external information which is not based on the fixed update. External and non deterministic things would be:
user input of any kind that has an effect on the physics system. That includes moving colliders.
Any sort of force or effect on the world state that is based on the game time or Update callback.
If your framerate drops below the set limit (by default 3 fps) which is determined by the maximum allowed timestep.
moving an object manually using the transform component. The Rigidbody has it's own position and rotation property.
Unity recently even introduced the ability to turn off automatic simulation and Simulate the system manually
ps: I'm actually still on Unity 5.6.1f1. In this version the autoSimulate property and the Simulate method aren't yet implemented. However the system was already deter$$anonymous$$istic back then. If something is not deter$$anonymous$$istic it's most likely you did something non deter$$anonymous$$istic.
@Bunny83 Thanks for the detailed response. I have no clue what I was doing when the scene was reacting differently each time I simulated it but I cant recreate it (it was a while ago). I read in so many places that Unity's physics system was non-deter$$anonymous$$istic but upon finding them again the most recent instance was Sep 2016 which isn't that recent. They must have changed it since then? I have run some of my own tests and everything looks good. It will be much easier just using Unity's build in engine! Thanks.
No, to my knowledge there hasn't been any changes in the past. Unity uses Physx as 3d physics engine. I found an old Unity installation on my old hdd. I fired it up and rebuild the same test there. It's Unity 4.5.1f3 (from 2013) and i get the exact same result.
People just are often mis-interpreting their results or forgetting about a non-deter$$anonymous$$istic change they did.
I'm confused then. From the research I did (which is what my original claim was based on) there are a lot of people saying the system isn't deter$$anonymous$$istic. Here are a few examples for Unity in particular:
Source 1 Source 2 Source 3 Source 4
I have seen a lot of people reference physX and how it isn't deter$$anonymous$$istic, meaning that Unity's isn't, which I confirmed here. At this point, I'm even more confused. As I said I ran tests and got identical simulations each time. Why would there be so many people saying it's not deter$$anonymous$$istic. So far I haven't found an official Unity source saying it is or is not so it's all just one person's word against another's.
:D I've found an even older Unity version on another hdd ^^. 3.3.0f4 (2010)
Recreated the test and basically got the same result. Though one thing was different. I simply spawn those 4 spheres between a frame that consists of 4 stretched cubes arranged in the x-y plane. Until now the spheres always happily bounced within this frame without ever getting a z force. In this Unity version however the spheres managed to escape the frame after some time (20 sec or so).
Nevertheless two simulation runs still yield exactly the same result after the 3000 physics frames (which is one $$anonymous$$ute btw). I tried again with frozen z constraint and (obviously) now they stay inside the frame. Though two runs with this setup also yield the same result.
As far as i can remember Unity did actually update the Physx version at least once in that time. So that might explain the difference to the more recent versions. However even back then the simulation was deter$$anonymous$$istic as far as i can tell.
Answer by Mazer83 · May 05, 2020 at 02:29 PM
@Bunny83 is mistaken, at least partially. The 2D physics engine is deterministic on the same machine, but only if you follow certain steps, and even then it won't be deterministic across all machines.
Source: https://support.unity3d.com/hc/en-us/articles/360015178512-Determinism-with-2D-Physics
If you want it to work the same on all devices, you'll have to write your own physics. Someone started on one already but didn't finish. You could use this project as a starting point (if you do make progress, please upload it on github and let us know! You could get more devs involved and end up with a better physics engine than you started with). As I understand it, the key to cross-platform determinism is fixed-point math.
Answer by unity_bTkJGG31azdikQ · Jun 04, 2021 at 03:21 PM
The key is the difference between Time.deltaTime
and Time.fixedDeltaTime.
Both of which are amounts of game time (not real time). Time.deltaTime
is calculated as the real time between frame calculations and varies, while Time.fixedDeltaTime
doesn't. The physics system uses Time.fixedDeltaTime
, so if your frame rate varies at all, you might have different numbers of physics updates between frames.
There are multiple ways to make sure these are in sync. I set Time.captureDeltaTime
, which keeps Time.deltaTime
constant (detaching the game from real time), since I often produce videos. Another option could be to move code from MonoBehaviour.Update
to MonoBehaviour.FixedUpdate
and use yield return WaitForFixedUpdate
in your coroutines.