Physics seemingly non-deterministic; How can I make it deterministic?

Hello Everyone,

To put my problem into some context; I am developing a multiplayer game in which clients can interact with entities in the physics space. I want other clients to be able to see the interactions which other clients make with objects.

My Method:
I know this is not the best way to achieve multiplayer physics, but this is the way I am currently doing it:
As it currently stands, when a client hits an entity, that client “claims ownership” of that entity, and will (effectively) send the:

  • PhysicsLocation, PhysicsRotation, LinearVelocity, & AngularVelocity

… of that entity to the other clients. The other clients then clear all forces from the entity in question, and apply those properties to the entity.

The Problem:
Theoretically, if the entities are setup to have the same Physical properties on all clients and the physical world being identical, performing the above should result in all clients simulating exactly the same outcome - with the entity starting and finishing in the same place… shouldn’t it??

It’s not like the entities are going in VASTLY different locations (e.g. I hit it with a tiny force and it ends up being catapulted across the world for the other clients) but they are none the less ending up in different places for different clients.

Possible Solutions:
Firstly, I know that this is not the best way of handling physics - I could for example have all physics simulated on the server side and then distributing the location/rotation of entities to clients… But I have chosen to do it this way.

I was thinking that maybe I am not getting equal results because:

  1. The clients are initializing their physics spaces with different random seeds (do these even exist for JME3’s bulletAppState?)
  2. The clients are simulating the physics at different in-game times?
  3. It could be that there’s some other force that I need to provide the clients with that I omitted from the list above

My Request:
Would you kindly be able to shed some light on why the clients are simulating some-what different results from the same inputs, and moreover, suggest how I can go about solving this problem?

I just need the other clients to be able to accurately replicate (deterministically) the same simulation on their side.

~Thanks in anticipation! ~ :wink:


When I refer to an “entity” I am talking about any Spatial for which I have created a collision shape and added it to the physics space; provided by bulletAppState.

For “realtime” physics you can’t. To have exact replicated physics space, each client should be sync on every tick.
Do you plan to rollback time and replay when an event from the past is received ?

I suggest you to read Gaffer on Games | Networked Physics (2006) and the comments (they include updates and demo)

How can I sync up the clients to some kind of universal/server-based physics space/time?

No, I don’t need to rollback time to replay any events from the past. (When might I need such a feature? …Instant replays?)

Bullet is deterministic except when you go below framerates of accuracy/maxSubSteps

Normen, when a client receives some new physics data to update an entity with, the client does the following:

    RigidBodyControl objControl = gameWorld.getMultiplayerPhysicsObjectByID(mpPhysicsObjID).getControl();
    MultiplayerPhysicsObject obj= gameWorld.getMultiplayerPhysicsObjectByID(mpPhysicsObjID);
    
    
    objControl.setPhysicsLocation(physicsLocation);
    objControl.setPhysicsRotation(physicsRotation);
    objControl.setApplyPhysicsLocal(true);
    objControl.setApplyPhysicsLocal(false);
    objControl.clearForces();
    if(isActive == true)
    {
        objControl.setLinearVelocity(linearVelocity);
        objControl.setAngularVelocity(angularVelocity);
    }
    
    obj.setOwnerShip(false);

Is there anything wrong with the code above which mean that I “go below framerates of accuracy/maxSubSteps”?

I can’t say because I don’t know if you go below framerates of accuracy divided by maxSubSteps

How do you enforce that physic data are “applied” at the right / same time on every client ?

MonkeyZone has code that does this including debuffering the time differences of the network connection.

I am applying the physics using the code above as soon as they are received. I am absolutely not sure that they are applied at exactly the same physics tick or ‘time’ on all clients. How can I do this?

You just dont,
Physic is one of the parts where age of empire2 style netcode is just not gonna work out , no matter what you do.

Do a sourceengine like system, where the server just sends periodicalls like every 50 ms the position and rotation.

Yeah, but even then it’s only a close guess… you can’t get truly deterministic local physics this way.

You’d have to count frames and send frame IDs with the server to client messages so that the exact frames can be replicated. This also requires stepping physics yourself so that you don’t miss frames if you haven’t heard from the server yet for some frame.

But maybe something like this is what you meant. In MonkeyZone, I don’t think the physics needs to be purely deterministic because you will be refreshing state occasionally anyway, right?

If I could set the frame/tick count to the same value across all clients (forgetting about latency for a second), would this allow for completely deterministic physics simulation on the client side?

Is it the physics tick which provides a certain amount of randomness to the simulation of a particular entity when it’s given values for PhysicsLocation, PhysicsRotation, LinearVelocity, & AngularVelocity?

I just want to point out that I am not just sending one single update from the client (let’s call it “a”) who interacts with an entity to the rest of the clients (let’s call them “b” and “c”). Instead, I am sending a new update for that entity every 250ms. This means that the entity always ends up in the correct location/rotation; but often clients b and c will incorrectly simulate the state of the entity between updates…

That is to say;

  • an update will arrive: b and c will correctly position/rotate/apply linear/angular velocity to entity in question
  • b and c now independently simulate the entity in their own separate physics space
  • b has simulated the entity to rotate + move slightly more to the left than a’s simulation
  • When the next update arrives, b’s version will jerk as it puts the entity on the correct path

As I see it, as all of a, b, and c are in identically setup physics spaces, there should be little/no jerking, as they should all be simulating exactly the same thing…?

You cannot accurately simulate the same exact time across computers. It is physically impossible. Someone will always be a little bit off.

So on one computer that bullet starts shooting a frame later than on some other computer and then everything changes. Small changes in state like this can have far-reaching ramifications even a few frames layer.

The only way to have purely deterministic behavior is to step the physics one fixed length frame at a time… and then only step it when you have all of that frame’s data from the server. Then everyone will have the same physics… they may not be running at exactly the same time but that doesn’t matter because you are playing back time from the server.

ie: there is no “random” in the physics math. Different output is caused by different input.

@pspeed Yes, I understand that you cannot have all clients simulating exactly the same thing at the same time.

What you go on to describe is exactly what I want to produce -

So, how do I achieve this? I don’t know how to step through the physics frames, or to even set the physics frame to begin with, so that late-joining clients can have their physics frame update to match that of the other clients.

It doesn’t matter if the clients are off by a a few milliseconds

Bullet always steps at a fixed rate and only uses the fed tpf as a “hint” about how many steps have to be done this frame / update step / whatever. But yeah, MZ uses the physics on the server as “main reference” and the client physics is basically just lookahead / interpolation.

Um, how about this guys?

Why don’t you just set up one actual game… and it hosts the physics… everyone else is just set up as a witness to it. They can send requests to the game, and the game itself puts it into play under its singular physics instance and then everyone else gets to watch that request in action… and request further things be put into play…

Isn’t that how it’s normally done?
er… did I just Occam’s Razor?..

edit how about this for the witnesses… yeah, they are going on their own physics routines which are way off according to the master, just to fill in the gaps between communications… but then, you just swap em back to where they “should be” on resync… It’s never going to be pretty if you try to fill in the blanks… especially in a lag type situation… That’s really all I can say at this time… hope it helps?

[BS WARNING!]
Oh wait… no, It just hit me… Occam’s Razor… Full on…

It’s such a simple and elegant solution, and it does perfectly fit the situation.

Use Quantum Entangled Computers.

That said, I don’t really know where you can find them at, yet.

Ok, you can start hate flaming me now. :stuck_out_tongue_closed_eyes:

Yes, but he already said he’s not doing it the best way. Otherwise, this response was kind of just reiterating the whole thread. :-/

hrrmm… you got a good point thar…

well, if the differences in time steps and floating point ops is the biggest deal then… um… why not granulate the system mathematically?

the fixed time step and naturally limited floating point ops helps to granulate the situation, so why not take it even further and do what they did for when games were still rendered in text. Only allow certain angles and velocities to emerge from fixed step calculations.

Think as if we are applying a toon shading method to the problem… sure we have a lot of colors it “could” be… but we limit it to only 2 or 3 shades of that color to be displayed. So… let’s do that to collision results… We decrease overall “believability” and increase cross interaction stability?

edit: further distance between time steps would help out as well if the objects were understood to stay in position of “collision detection” until the next time step “unfroze” it to resume with it’s new results.

That might help