Box2D World Inconsistent Movement Speeds

I currently have a game using Box2D, and the movement seems to be inconsistent. For example, when i move the player character across the map (it’s a platformer), sometimes it moves at ‘normal’ speed, and sometimes slower. It also happens with the effect of gravity, sometimes the player falls ‘normally’ and sometimes slowly.

The problem seems to be random, because it doesn’t happen every time.

The player character is about 1 m wide by 2 m tall, and all the platforms are about 0.5 m thick and range from 2-10 m long, except for the ground, which is about 60 m long. All objects except for the player are static bodies, and created using the Box2DMapObjectParser.

Any ideas on what might be causing the problem?

This may be a timing issue, i.e. at some times you are updating the world with large time intervals, at some other time with short intervals, making it appear as if the character moves faster or slower, while in fact the entire physics world is updated at a faster or slower pace. Does the World.step(timestep, velocityIterations, positionIterations) function get called at a consistent rate with a consistent interval? (for example 30 times per second with a timestep of 1/30)

Otherwise I would have no idea what this could be.

I’m pretty sure it’s being called at a constant rate, because it’s only called in the render method of the libgdx screen.


@Override
public void render(float delta) {
        ...
	world.step(1/60f, 8, 3);
        ...
}

Unless I’m meant to use the delta time as well? world.step is not being called anywhere else.

Yes, you should multiply all your movement code by delta. This will smooth the movement out between frames, so it should fix some issues.

So instead of doing playerBody.setLinearVelocity(v), I should use playerBody.setLinearVelocity(v*delta)? I thought Box2D took care of the delta timesteps.

I have no idea what Box2D does and doesn’t do, you should check into it. But yes, for all movement you should be multiplying by the delta.

Although the box2d manual specifies that the world should step with a constant step time, You might want to experiment with


@Override
public void render(float delta) {
        ...
   world.step(delta, 8, 3);
        ...
}

Your code should work fine if you are 100% sure that the render(float delta) method is called 60 times per second. I’m not 100% sure but I think that LibGDX will try to call this method as fast as possible, which in some cases lead to a lot of world.step calls (i.e. when little has to be drawn on screen and FPS is high) and in other cases to fewer world.step calls (i.e. when FPS is low), slowing the physics down.

Theres some a nice article on time step on http://gafferongames.com/game-physics/fix-your-timestep/. Here’s what I do, it’s not perfect but it avoids your problem (if that is the problem):

public abstract class AbstractGame implements ApplicationListener {

	public static final long ONE_SECOND_NS = 1000000000;
	public static final int MAX_FPS = 60;

	private int maxUpdates = 10;

	private long lastTime = System.nanoTime();

	@Override
	public void render() {
		long time = System.nanoTime();
		long timeDelta = time - lastTime;
		float timeDeltaSeconds = timeDelta / (float) ONE_SECOND_NS;
		lastTime = time;

		// Update the game state in capped time steps (in case we're running too slow)
		int updateCount = 0;
		while (timeDelta > 0 && (maxUpdates <= 0 || updateCount < maxUpdates) && !paused) {
			// Update using a time step in seconds
			long updateTimeStep = Math.min(timeDelta, ONE_SECOND_NS / MAX_FPS);
			float updateTimeStepSeconds = updateTimeStep / (float) ONE_SECOND_NS;

			// Update here (also call world.step here)

			timeDelta -= updateTimeStep;
			updateCount++;
		}
		
		// Do rendering here
		
		// Limit the maximum FPS if this is not a loading screen
		long sleepTime = Math.round((ONE_SECOND_NS / MAX_FPS) - (System.nanoTime() - lastTime));
		if (sleepTime <= 0)
			return;
		long prevTime = System.nanoTime();
		while (System.nanoTime() - prevTime <= sleepTime) {
			Thread.sleep(1); 
		}
	}
}

Edit: I’d recommend against using a varying time step in Box2D, as this may lead to other difficulties (according to the manual).

Box2D indeed takes care of delta timesteps and you should never do setLinearVelocity(v*delta), unlike opiop65 suggests. However, by setting velocity of objects directly you are interfering with the physics simulation. Maybe you are better off using impulses, as described here.

@xsvenson: putting delta in the timestep definitely made the physics run much more smoothly and consistently, but the frame rate seemed to keep changing between 30 and 60. With a constant timestep (1/60f), the FPS is about 60.

@Grunnt: I’ll try out your method tomorrow once I get some sleep, because I’m really tired at the moment. That’s quite an interesting idea though, because I never would have thought of manually controlling the game/render loop and Thread. I thought libgdx took care of that stuff.

Anyways, thanks everyone for all the quick replies! Good night

EDIT: Just saw your latest reply as I posted my reply. I initially used impulses, but that made the controls feel “slow”, because it took time for the player to accelerate. Player movement feels a lot more snappy by directly setting the velocity. Thanks for the tip though, I’ll try playing around with impulses again. Anyways, really appreciate the help, thank you very much.

Sleep well ;D

As Grunnt explained, with very high FPS and with very low fps, the world step still calculates the physical world with 1/60 timestep. This means with 60 fps You get a resolution of 1, with 600fps You get a resolution of 10 (10 times faster). If the FPS is capped at 60, this is not much of a problem, but if the FPS gets lower than 60, it, once again, gets to be a problem.

On desktop, the default cap is at 60fps, on adroid, the cap can be device dependent (60fps, 80fps, 30fps), this means, on those device, Your game will run differently.

You reporting a FPS drop might be caused by Your box world just taking lots of time for calculations.

With libgdx You should have no reason to roll Your own rendering loop, with years of human hours spent on the engine and running well on more restricted environment (android) , one can assume that the rendering loop is quite well optimized.

[quote=“Rayexar,post:10,topic:44731”]
Happy to help! Be sure to look into the differences between applying impulse and applying force, as applying impulse should help you get instantaneous effect, as opposed to applying force.

[quote=“xsvenson,post:12,topic:44731”]
Whether a LibGDX game has a framerate cap at 60FPS is entirely up to the developer as far as I know. You can make a game run at 6000FPS or at 6FPS, it just depends on how you code it, and things like whether v-sync is turned on or off.

[quote=“xsvenson,post:12,topic:44731”]
One can assume that this loop is quite well optimized, but this is quite different from one having a loop with a fixed time step. ;D In order to decouple world updates from rendering (which is really neccessary in physics-based games precisely to avoid the problems the OP has) you need to develop a custom game loop that seperates updates from rendering, so update speed no longer depends on FPS. LibGDX out of the box does not do this (which is not a shortcoming of LibGDX, it’s just something you have to do yourself). Again, take a look at http://gafferongames.com/game-physics/fix-your-timestep/ which explains this a lot better than I ever could.

Yes, as I said, the default is 60fps. However, on android devices this has been capped for You.

While a fixed step update gives more predictability and stability for physics simulation, it is not directly necessary. For using physics with delta You just need to be aware of the shortcomings.
I would like to point out that all libgdx box demos run with the regular libgdx rendering loop. With the default fps of 60 (which is even achievable with most android devices and in browser), the max delta is theoretically capped, giving You a nearly “fixed step” simulation. Of course, the fps could get lower, in which case, indeed, the simulation can take a hit or experience some artifacts.

The question here is rather do You care or does it matter ? I just know I am using the regular libgdx and box and for me it’s good enough.

[quote=“xsvenson,post:15,topic:44731”]
That is a very good point ;D

If for some reason you don’t want to run fixed time step simulation you should still always cap your delta time to some sane value. Usually good value is inverse of target fps halved. So target fps is 60, target delta time is then 16.6ms so cap would be (1/30) ms ~ 33.33ms. When fps for some reason drops significantly you want to avoid tunneling artefacts or explosions at physic simulation. In these cases you can just choose to game either lag a bit behind or run multiple steps to get simulation to catch real time.

@Grunnt: Your update loop did the trick! In fact, it made all the physics a lot smoother and faster as well as more consistent. I highly recommend anyone who’s using Box2D with libgdx to use this as well

Great! Glad to hear it.