- Home /
Is a Unity simulation deterministic?
Yhis is something useful mainly for multiplayer RTS games, but could be useful for any other game that needs to be able to execute a game in lock-step on multiple non-identical machines. To be fully deterministic in this sort of sense, the following would all have to be true:
RNGs are instantiated, called a consistent number of times in a "turn" (that might be 200ms), and give predictable output during that time period.
Floating point math, plus any other math, gives predictable results on all processors (AMD vs Intel, x86 vs x64, etc) and operating systems.
There is always a consistent number of simulation cycles per "turn," regardless of the number of frames drawn to the screen.
Basically, I'm wondering if it is possible to build a modern multiplayer RTS in Unity -- obviously single-player is no problem, and other networking models make multiplayer action/FPS/etc games quite possible in Unity, but I've not seen anything relating to simulation determinism in my investigation into Unity so far.
Lo and behold, as soon as I ask this I find the FixedUpdate method while looking at something else. That looks like it would handle #3 on my list, even though #s 1 and 2 are then still open.
@x4000 - Any conclusions on your investigation x4000? I'm having deter$$anonymous$$ism issues running in the same machine :(
@roberto_sc See below, I posted comments with my findings -- thanks for re$$anonymous$$ding me!
Answer by Eric5h5 · Mar 16, 2010 at 07:18 PM
Random numbers can be made 100% predictable cross-platform by using Random.seed. You can set the number of simulation cycles through various methods (FixedUpdate, InvokeRepeating, etc.). The only thing I'm not sure about is the floating point math across different systems. As a side note, the physics engine is not consistent, even on the same machine.
Okay, that is good to know on both counts. So I would be better off just using a fixed-int math implementation in such a circumstance, and custom physics/etc simulations.
It's possible the floating-point math is fine; it seems to be the same across OS X and Windows (PPC and x86), but I'm not 100% sure.
I would actually recommend System.Random in this case. It's an instantiated class, so you don't risk making predictable sequences unpredictable when introducing new scripts calling the globally available RNG, which is stateful.
"the physics engine is not consistent, even on the same machine" I think you're probably right, but I'm looking for some evidence to confirm this statement. Could you point me to your source?
@SmallPileofGibs: It's possible that statement is out of date now, with Unity 3. I haven't run any physics tests there yet. In Unity 2, things like putting a sphere on a slope and running the scene several times could cause the sphere to end up in different spots each time even though you haven't changed anything at all.
Answer by x4000 · Aug 24, 2011 at 01:34 PM
Wow, it's been quite a while on this question, and I meant to post back with my findings. First of all, I can't really speak to things like the physics or networking simulation in Unity 3D, because I don't use any of that. We don't use GameObject at all, except one for playing back audio.
That said, we have a bunch of scripts that we run via a call stack starting with Update, FixedUpdate, and OnGUI in our main camera's script. THOSE are definitely fully deterministic, insofar as they would need to be for a multiplayer RTS game.
We still do not use floating point math for any simulation-relevant calculations, but instead use our "Fixed Int" solution. We use the Lidgren library for networking, which is what we used before we ported our games to Unity.
In the end, we have two Steam-published solo/multiplayer games (AI War and Tidalis) running Unity, with north of 100k customers, and they are both running great even with one player on OSX and another on Windows or Linux/WINE.
If I had to guess I would say that the Unity physics simulation is probably NOT fully deterministic in the fashion you would need for an RTS to run in lock-step, but I don't have proof one way or the other. That just seems like an asynchronous, floating-point sort of bit of calculation, and especially with how unity scales to load that's going to be inherently non-deterministic from what I can see. For an action game style of networking model that doesn't matter, but for an RTS that might be what is the cause of the problem roberto_sc is seeing.
@x4000 - Thank you. So far we were able to keep simulation deter$$anonymous$$istic between machines with the same OS type (but not $$anonymous$$ac+Win, unfortunately) by rounding positions before the FixedUpdate.
@roberto_sc: that seems like it would negate a lot of the benefits of having floating positions in general; smooth movement, etc. We use this, ins$$anonymous$$d, which takes all the guesswork out: http://stackoverflow.com/questions/605124/fixed-point-math-in-c
That said, you have to choose between either having a small precision or a small max number or using 128-bit integers, etc. We go with a reasonably small precision (three decimal places), but that's more than enough for our purposes in AI War and Tidalis, even at 60fps in the latter.
Answer by Jaap Kreijkamp · Mar 17, 2010 at 12:34 AM
It will be quite hard to get this right as when working with floating point numbers there's always the possibility of slight variation between platforms that can play up over time, but worse, timing: FixedUpdate is run at fixed interval except when things go wrong. Switching between applications could result to missing a few update cycles (even when background running is active), or any other instance where CPU is overloaded for a few 100ms.
Well, it's really not important that FixedUpdate run on a specific exact ti$$anonymous$$g interval... but rather, that it runs an exact number of times in that scenario. In other words, ins$$anonymous$$d of using elapsed time to calculate offsets and such, game objects have to move a certain amount per cycle, and the number of cycles has to match. $$anonymous$$y existing successful indie RTS game does this quite reliably. The nature of my inquiry is to see if it is at all feasible that I can eventually port that over to Unity; right now I'm working on another project that does not require that precision, luckily.
@Jaap-$$anonymous$$reiijkamp, you can try to increase $$anonymous$$aximum Allowed Timestep to avoid (but not resolve) this problem. http://unity3d.com/support/documentation/Components/class-Time$$anonymous$$anager.html
Answer by jpthek9 · May 09, 2015 at 12:24 AM
Hi, I know I'm a little late but here's a thread for the deterministic physics engine I made: http://redd.it/358hl6 . It comes with a lockstep server and multiplayer setup for RTS games and the like. Sorry for the shameless plug hehe, but I hope this package will be useful for people who are making a lockstep game.