Does different time step also makes different result?

Post Reply
tomson0119
Posts: 5
Joined: Tue Feb 08, 2022 10:18 am

Does different time step also makes different result?

Post by tomson0119 »

I'm currently making online racing game using bullet physics.

I'm using btDiscreteDynamicsWorld, and calls stepSimulation every update.
The timeStep is less than 1/60 but it will be bigger as I bulid more object.
I know that it may loses time if time step is bigger than fixed time step, So I gave maxSubStep parameter as 2,

Code: Select all

stepSimulation(timeStep, 2)
This is client side.

I'm also simulating physics world in server side too. In this case, I manually set duration of physics update to 1/60.
So timeStep in stepSimulation is bigger than 1/60.

These two simulation has to be same, so I can synchronize positions of players.
But I'm afraid these may simulating different speed, and gives different result.
Do I something wrong about it? Should I change something?
By the way, Client and server are updating vehicle component based on timeSteps.

[edit]
I need to sync these two simulation, so if these two are not different, how to get same position of vehicle from both dynamic world.
I've tried, motionState->getWorldTransform, rigidbody->getWorldTransform, rigidbody->getInterpolationWorldTransform.. but it doesn't match.
I'm using btDefaultMotionState class.
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Does different time step also makes different result?

Post by drleviathan »

Yes, a different sub_step will produce different results. In particular, at longer sub_steps some object-object interactions could tunnel instead of collide. Even if you turn on continuous collision detection (CCD) the subtle differences introduced by different sub_steps will cause two otherwise identical simulations to drift apart. In fact, two distinct simulations at the same sub_step will drift apart due to floating point error, randomization in constraint solutions, and different CPU architectures. Physics simulations can be made reproducible so they always have the exact same result given the exact same input but Bullet is not that way by default.

It sounds like you're trying to run a distributed simulation: one on the server and one on the client. This is possible, even at different sub_steps. To make a fun game the physics doesn't necessarily have to be exactly right, and in a distributed system the various simulations have to have a way to negotiate final results at their boundaries anyway.

Understand the difference between time_step and sub_step. The time_step is the time given to the world->stepSimulation() call. The simulation will only move forward one sub_step at a time. In an attempt to explain the difference I offer this hypothetical scenario:

Suppose you set your sub_step to be 1/60 of a second (16.67 msec), but your game loop is running at approximatly 45 Hz (22.22 msec). Each frame you would measure the time since the last step and feed that to world->stepSimulation(time_step). The world will advance forward 1/60th of a second and accumulate the remainder (22.22 - 16.67 = 5.55 msec) for later. Eventually it accumulate enough remainder to take a second sub_step during the step.

Your simulation could "lose time" when: the number of sub_steps per step is limited AND each step takes more time to compute in the real-world than time advances in the simulation (e.g. you're trying to simulate too many things or your things are too complicated). The reason it is recommended you limit the number of sub_steps per step is because otherwise you risk the "spiral of death" problem where the sub_steps pile up over subsequent simulations as it takes too long to keep up with real-world time flow --> disaster.

The reason motion_state->setWorldTransform() provides a different value than body->getWorldTransform() is because of the aforementioned remainder accumulation between time_step and sub_step. The MotionState will provide an world_transform that has been extrapolated forward by the remainder. This is a convenience feature which can reduce aliasing effects (e.g. stuttering) when the render framerate is different from the simulation's sub_step framerate.
Post Reply