Physics speed depends on frame rate

I have a question about the physics of Defold and I am unsure which factors are responsible for calculating physics.
I’m working on a game where a ball is thrown at a target. All objects have dynamic collision objects and are automatically handled by the internal physics. The ball is thrown towards the target by a single apply_force.

msg.post("#collisionobject", "apply_force", { force = vector1 * 2000, position = go.get_position("#collisionobject") })

In addition, I want to roughly display the trajectory of the ball and I found this great example. For the trajectory to fit, I had to include the weight of the ball and the dt in the calculation. The calculated trajectory now seems to fit well.

self.initialV = vector1 * 2000 * (1/mass) * self.dt

My game should also work correctly on devices with weaker hardware. To test whether the predicted trajectory is correct, even at a lower frame rate, I set the “Frame cap” option to a low value, such as 30, in the game.project. It struck me that physics suddenly seems to run faster. The dynamic objects fall faster to the ground. The ball also flies less far despite the same force.

I suspect that the force has to be calculated depending on the frame rate. So when I call apply_force, I guess I’ll have to set the value against the current dt, e.g.

msg.post ("#collisionobject", "apply_force", {force = vector1 * self.dt * 12000, position = go.get_position ("#collisionobject")})

But even then the ball flies with a frame cap of 30 less than at 60fps, which makes the predicted trajectory no longer fit.

Why is this and why are all objects moving faster at a lower frame rate?

I’ve noticed the same behaviour myself but haven’t really had time to dig in to the issue more. Are you using 2d or 3d physics by the way? We use Box2D for 2D and Bullet for 3D.

I suspect (but haven’t confirmed yet) that the force supplied in “apply_force” is applied for one time-step in the physics integrator. That means that a large time-step will yield a bigger acceleration, since the force acts on the body for a longer time than for a small time-step.

If this theory is correct, you should be able to calculate a factor to scale your force with to get consistent behaviour across different time-steps. For example, run the game with time-step 1/60 and tune the force applied. In runtime, scale the force to apply by a ratio between the actual time-step and the fixed one. E.g. when running at with 1/30 apply (1/60) / (1/30) -> 0.5 scale factor to the force.

Caveat; a simulation will produce different results when using different time-steps regardless.

4 Likes