Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Unity Physics and Making it Deterministic

Discussion in 'Physics' started by jpthek9, Feb 5, 2015.

  1. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    Determinism of Unity's physics engine has been a reoccurring topic within the community and yet I don't feel like it's been explored very much as people often condemn it because it uses floating point math.

    Many games need determinism for things like synchronous simulations across the network or small, elegant replays. Common knowledge so far has been that the Unity's physics is not deterministic because of floating point imprecision. According to this article, floats have accuracy of at least 6 digits which, I think, is more than enough precision for physics.

    I never saw why the inputs and ouputs for physics couldn't just be rounded to the significant digits as this would take out nearly all randomness caused by floating point imprecision. Furthermore, certain games like RTS require simulation at very slow intervals - maybe 10 per second - so not only would there be less room for inaccuracies, but the rounding would also cause a less drastic change on the simulation.

    As of far, I can think of no reason why through the use of heavy rounding and a low simulation rate the physics can't be made deterministic. I don't think there are any random factors (besides imprecision) in the PhysX or Box2D engines and the floats definitely have enough precision for smooth rounding. At the very least, I think the collision detection can be used and the impulses calculated in a custom manner. This is much better than the alternative of having developers coding everything from scratch. Do you think this will work and if not, why?
     
    Last edited: Feb 5, 2015
  2. cl9

    cl9

    Joined:
    May 31, 2013
    Posts:
    417
    Physics across different platforms and architectures, or on a single machine needing reproducible results (play backs), would seem to require either an authoritative server or fixed point calculations.

    Or there is an alternative approach?
     
  3. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    Read
    Read OP. In any case, what makes fixed point math so special over floating point math when both have sufficient degree of accuracy?
     
  4. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    I made a test to see whether or not Unity PhysX can be made deterministic. Please check it out here if you're interested in helping to solve this mystery.
     
  5. cl9

    cl9

    Joined:
    May 31, 2013
    Posts:
    417
    I don't think it would be an argument of the accuracy of the calculation, but instead, the reproducibility of the calculation. Or perhaps not?

    When I have my Windows machine working again, I'll check out the link.
     
  6. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    It seems unintuitive that 1.1 + 1.1 won't equal to 2.2 on all computers whereas 1.00000000001 + 1.00000000001 might not equal 2.00000000002 because there's a lot more needed to be stored in just 4 bytes. That's basically what rounding everything is doing - scaling down the calculations to more manageable numbers for the computers.
     
    Last edited: Feb 7, 2015
  7. cl9

    cl9

    Joined:
    May 31, 2013
    Posts:
    417
  8. MatthewW

    MatthewW

    Joined:
    Nov 30, 2006
    Posts:
    1,355
    An additional complication with true input-based playback for a full scene/match/whatever is the order of operations for the objects themselves. Lots of gameplay things (i.e. jump pads, boosts, whatever), might need to apply forces to objects in the same order in your replay as in the original version to get the same result.

    That kind of stuff requires determinism throughout the engine, which Unity isn't well suited for, especially for object creation/deletion. If you create 10 pieces of physical shrapnel on an explosion, they're going to have be created in the same order so they handle collisions in the same order later, etc etc...
     
  9. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    Are you saying calling Instantiate(Obj1) before Instantiate(Obj2) doesn't necessarily mean it gets instantiated first?
     
  10. MatthewW

    MatthewW

    Joined:
    Nov 30, 2006
    Posts:
    1,355
    No, but many events in Unity are ordered by either when they were loaded or by GUID or other essentially random elements. If you have a bunch of game logic scripts, and they're all doing some kind of distance check or whatever in Update/FixedUpdate, you need to make sure you control the order in order to provide fully deterministic playback.

    You can actually set script execution order relative to each other (so ScoreManager fires before RocketExplosion or whatever): http://docs.unity3d.com/Manual/class-ScriptExecution.html

    But even then, if you have 10 objects with RocketExplosion on them, you still need to make they all execute their Update/FixedUpdate in the same order deterministically in order for full deterministic playback to work...
     
  11. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    Forgive me for the ignorance, but why is this?

    By the way, I've conducted more tests on different platforms - sadly, it's not possible to make Unity's physics deterministic. They already round positions to the 2nd decimal place and give you no control over what happens in between the roundings.
     
  12. MatthewW

    MatthewW

    Joined:
    Nov 30, 2006
    Posts:
    1,355
    It's a good question!

    I'm getting a little out of my depth with low-level stuff, but the very general answer is that there are lots of unordered data structures in use with engines. Something like HashSet at the C# level is a good example of a fast lookup that can't provide ordered results. It's basically just an optimization tradeoff.

    Most of these data structures are using an object's HashCode, which can you can see in Unity via the debug Inspector (top-right menu toggle) or via:

    Code (csharp):
    1.  
    2. Debug.Log("My hash code is:" + this.GetHashCode());
    3.  
    Reload the same scene, and that code changes for each object.

    So even with float precision wrangled you're still going to need to architect an engine so that multiple collisions in each frame are processed in the same order, your Update/FixedUpdate logic is in the same order, and that you aren't just using any random numbers that aren't passed through some kind of seeded random number generator. It gets pretty deep.

    Even at the physics level, truncating/rounding to a defined range is going to bubble up and degrade your actual physics simulation fidelity pretty badly. That kind of limited precision doesn't seem so bad if you imagine rounding a position every frame, but to do collisions deterministically you're going to need to round everything at every step (calculating the angles of surfaces, the forces involved, etc etc)...
     
  13. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    Oh, that makes sense. Much appreciated for the explanation.
     
  14. Roni92

    Roni92

    Joined:
    Nov 29, 2013
    Posts:
    226
    It's rounded for performance reasons. Its much more important than extreme-precision.
     
  15. pantomimecorp

    pantomimecorp

    Joined:
    Aug 16, 2014
    Posts:
    3
    Rounding floating point numbers to decimal places is not accurate because floating point numbers are not represented in decimal, they are represented in binary. So when you round a number like 1.0011043425546 to a decimal representation 1.001, that is NOT necessarily precisely represented as that exact decimal number. You get just as much inaccuracy when you round to decimal digits as you do when you don't round at all.

    Also, there are many numbers used by the physics simulation that are very small, like in the range of 0.0000000000111 to 0.0000000000222, which can be represented accurately as 1.11E-10 to 2.22E-10, so rounding them off to the nearest 0.0001 completely throws those values away. Rounding to decimal digits is NOT a valid approach to accurate numerical simulation.
     
  16. jpthek9

    jpthek9

    Joined:
    Nov 28, 2013
    Posts:
    944
    What if the numbers are rounded to powers of 2? I.e. Math.Round(X*1024)/1024
     
  17. yoyobbi

    yoyobbi

    Joined:
    Nov 26, 2013
    Posts:
    16
    No amount or method of rounding floating point numbers will yield deterministic answers.

    Suppose two different machines perform a sequence of floating point operations with a correct mathematical answer of 1.5. Machine A gets the result 1.49999999999999999 while Machine B gets the result 1.500000000000001. Machine A rounds to 1, Machine B rounds to 2.