Closed totoze closed 5 years ago
Hi
I think the issue might be the following:
(1) When you resize the screen, there is a sudden perf spike and the elapsed time passed to PhysX is large (2) Due to this large elapsed time, the effect of gravity on the spheres is large (large input velocity, leading to a bounce or, if a collision is missed, the spheres will pass through the ground (3) If the collision(s) were missed and the frame rate returns to normal, there is a large impulse applied (proportional to penetration * 1/dt) to correct the error, leading to the spheres exploding into the sky.
A time-step of 2s will lead to a stationary sphere's velocity becoming -19.6m/s (-9.8*2) and it instantaneously travelling 39.2m below its previous position due to how Euler integration works. If it was positioned just above the ground and the frame rate returned to 1/60, it would need to correct 39.2m of error in 1/60th of a second, leading to a new velocity of 2352m/s, which is apparently 6.86x the speed of sound!
As a general rule, these kind of bad situations can happen if you simulate physics using variable, unbounded time-steps. It is recommended that you either simulate using fixed time-steps (ideally) or, alternatively, semi-variable time-steps, e.g. there is some variability but you do not allow the time-step to become large. What constituted "too large" depends on your particular use-case but most game engines won't simulate physics with time-steps larger than 0.03333s by default.
If you simulate with fixed time-steps, you may need to simulate multiple times for each rendered frame if your frame rate is low. If you run variable time-steps, you would just need to simulate once per frame. However, in both cases, you should clamp the total amount of time that is simulated to ensure that (1) performance does not suffer if you are simulating multiple fixed time-steps and (2) that behaviour does not become unacceptable if you are simulating variable time-steps. This would have the effect of your simulation running slower than real-time, but this would be preferable to bad behavior or a large number of physics simulation calls limiting performance.
With regards to kinematic bodies - you can emulate a kinematic by adjusting the mass/inertia and disabling gravity on bodies, but the more efficient way to simulate kinematics is to set the PxRigidBodyFlag::eKINEMATIC flag on the rigid body. If you do this, PhysX can skip some work inside the solver with those bodies. In addition, if the bodies will never move, you should use PxRigidStatic rather than a kinematic PxRigidDynamic as this will reduce memory usage and improve performance compared to kinematic bodies.
Hope this helps
Thanks you for your detailed answer. regarding the option of simulating with fixed time steps something I saw game engines like unity(using physX) do and seems like the more correct solution for the problem. Would I still be able to take advantage of multiple threads and run the simulations (some frames will have zero simulations and others a few simulations) asynchronously?.
the issue is solved. I implemented a fixed update event firing 60 times per second. I stopped using physX asynchronously ,but actually got a performance increase since I have to make less calls to physX when my application is running on more than 60 fps. I implemented the fixed update event like this:
//very simplified example code
float fixedTime = 1.f/60.f;
float deltaCache = 0;
void DoFrame() {
auto start = Time::now();
PollEvents();
renderer.Clear();
Events::OnUpdate();
deltaCache += deltaTime;
for (int i = 0; i < floor(deltaCache / fixedTime); i++)
{
Events::OnFixedUpdate();
deltaCache -= fixedTime;
};
Render();
SwapBuffers(Screen::window);
auto end = Time::now();
deltaTime = ((fsec)(end - start)).count();
}
Hello. I have noticed an unexpected behavior from the physics simulation when the delta time (or elapsed time) value of my application is higher than normal. (about 0.5 to 2.0). The simulation seems to make all non kinematic move up (kinematic done by setting mass and inertia to zero , according to the docs :
Here's the code used to init physX
Every frame I do
mScene->fetchResults(true);
before update andmScene->simulate(deltaTime);
after the update. Since im sure it's hard to visualize the issue I have a 30 sec GIF of the bug in action. On the gif you can see the balls which are dynamicbodys with a sphere shape attached bounce up when delta time is high (in this case delta time is high since the window resize event blocked the main thread)Note the actors don't disappear at the end of the GIF they just went very high up and will fall from the sky back to the ground (which is a dynamic body with a box shape attached and a mass set to zero). It also seems like the amount in which the actors go up increases when the value of delta time is higher. Here's the code running every frame
And the ground is sated up like this:
physX is also sending three massages only at the start of the simulation :
I assume it's something that has to do with the first frame only and isn't really related to current issue. What am I doing wrong here ?