Search Unity

Dealing with floating point precision

Discussion in 'Multiplayer' started by NimbleSprite, Dec 3, 2021.

  1. NimbleSprite

    NimbleSprite

    Joined:
    Nov 3, 2017
    Posts:
    34
    Thanks for any help with this simple question :)

    For a multiplayer RTS game using lockstep networking, we need to ensure that floating point numbers are truncated before the point where inconsistencies across different processors will arise. For instance:

    5.12345678 needs to be truncated to 5.1234 or so (before the 5th, 6th, or 7th decimal as I understand it).

    Is this an OK method of dealing with these types of desync errors? Will it ensure determinism? Or is it necessary still to use a fixed point library in order to get around this issue because things can still happen internally to cause desync?
     
  2. luke-unity

    luke-unity

    Joined:
    Sep 30, 2020
    Posts:
    306
    Truncating floats will not ensure determinism. It will greatly decrease the chance of a desync but with hundreds of floating point operations happening each tick there will still be a very high chance of a desync. I'd definitely recommend to go with fixed points.
     
  3. zh99998

    zh99998

    Joined:
    Mar 2, 2020
    Posts:
    18
    Is there any simpler way to achieve limited determinism? for example only support recent n-years x64 cpu
     
  4. NimbleSprite

    NimbleSprite

    Joined:
    Nov 3, 2017
    Posts:
    34
    Thanks a lot for your reply Luke. Do you have an idea if division in integer math is deterministic by the way? Would this equation: (int x / int y = int n) give the same 'n' on different machines? Or is even division with ints enough to cause desync? I just know that division with ints always becomes an int somehow, but not sure how the decimals are dealt with internally.
     
  5. luke-unity

    luke-unity

    Joined:
    Sep 30, 2020
    Posts:
    306
    Int and long division are deterministic across all CPU architectures.
     
  6. luke-unity

    luke-unity

    Joined:
    Sep 30, 2020
    Posts:
    306
    Yes this can work but you'd have to be really careful in ensuring that the devices are actually all doing the same calculation. If you go down this route I'd recommend to make sure that:
    - You build a checksum of the state of each machine every X ticks and compare it to all other instances to ensure that there is no desync. This is generally speaking good practice for determinstic games anyways
    - You write tests which run on the cpu models you want to support and check their checksum hashes to ensure that they are determinstic.

    I have seen floating point being used to achieve determinism for games which were launched for consoles and without cross play functionality. Since all the consoles use the same CPU you can guarantee that they end up with the same results. For mobile and PC this will be much more tricky, as even modern CPUs can use different ways to calculate floating points.