• 11
• 9
• 10
• 9
• 11

# Avoid game state interpolation with fixed time step

This topic is 411 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm trying to fix the time of my engine to do proper collision detections. I have read this article

Fix Your Timestep! (I think I misunderstood some concepts) and this good response http://gamedev.stackexchange.com/a/12760 , but I don't really want to keep two copies of my world state, so I've tryied to do a forced update with the remaining accumulator time. This is a resume of my game loop:

...

float accumulator = 0.0f;

Timer::ELAPSED = 0;   // Uint32
Timer::LAST = SDL_GetTicks();    // Uint32

Timer::deltaTime = 0.01f;

while (state != SceneState::EXIT) {

updateInput();

Timer::NOW = SDL_GetTicks();
Timer::ELAPSED = Timer::NOW - Timer::LAST;
Timer::LAST = Timer::NOW;

accumulator += (Timer::ELAPSED / 1000.0f);

while (accumulator >= Timer::deltaTime) {

update();
accumulator -= Timer::deltaTime;

}

/* The forced update part */

Timer::deltaTime = accumulator; // Changing the delta time to a value < 0.01f
update();
accumulator = 0.0f;
Timer::deltaTime = 0.01f;

/****                ****/

draw();

...



While this seems to work (now there are no flickering effect because there is a guaranteed update call with the remaining time) I think this breaks the concept of fixed time step (now Timer::deltaTime vary in the forced update). Have you got some ideas of how to do it properly?

Edited by ArtLem

##### Share on other sites

Why not just do a variable time step in the first place? :)

##### Share on other sites

Why not just do a variable time step in the first place? :)

Hi, thanks for the reply. I've tried a variable time step too, but I've got some strange behaviours with the collisions (I'm moving the objects forward to check if they collide, but with variable delta time I don't know their future positions).

Edited by ArtLem

##### Share on other sites

I can understand that you might not want to keep 2 copies of the world state, but a good compromise is to keep 2 copies of each object's position. The cost per object is minimal and being able to interpolate position at render time should be more than enough to hide most aliasing glitches and keep things smooth.

Another option, not mentioned often as it should be, might be to render at a fixed rate and perform physics updates at a strict multiplie of that rate. That way the accumulator would always be zero at render time; the downside is that you have to hit your rendering rate or see the game slow down. That may be an option for you.

##### Share on other sites

I can understand that you might not want to keep 2 copies of the world state, but a good compromise is to keep 2 copies of each object's position. The cost per object is minimal and being able to interpolate position at render time should be more than enough to hide most aliasing glitches and keep things smooth.

Another option, not mentioned often as it should be, might be to render at a fixed rate and perform physics updates at a strict multiplie of that rate. That way the accumulator would always be zero at render time; the downside is that you have to hit your rendering rate or see the game slow down. That may be an option for you.

Thanks for the reply, probably I'll try the first option, but I'm curious about how second way works, if I understood correctly, you say that I can duplicate, quadruplicate, etc the update loop matching the render rate.

So, for example, for a draw call, call twice to update method?

##### Share on other sites

Yes, or any method that is equivalent to that. If you're rendering at 30fps but perform physics updates at 90fps then you'll have always done 3 fixed updates of physics when you're about to render, so there is no need to interpolate; you already have the exact values you want to display.

with variable delta time I don't know their future positions

This is a slightly different problem, however. If the object is moving straight, then you could test the region the object is moving through rather than attempting to test a fixed position.

##### Share on other sites

Yes, or any method that is equivalent to that. If you're rendering at 30fps but perform physics updates at 90fps then you'll have always done 3 fixed updates of physics when you're about to render, so there is no need to interpolate; you already have the exact values you want to display.

with variable delta time I don't know their future positions

This is a slightly different problem, however. If the object is moving straight, then you could test the region the object is moving through rather than attempting to test a fixed position.

Time to test some code, many thanks!

##### Share on other sites

In Caveman 3.0 I'm currently using a user defined frame rate limiter.  update runs at 15 Hz.  the user chooses a target FPS.  The target FPS determines the frame time for the limiter. an accumulator accumulates frame times, and update consumes frame time in discrete chunks so it works out to 15Hz. update also scales all deltas based on FPS.

So you set it for 60 fps, and assuming your hardware can do 60 fps, it runs at 60 fps. knock it back to 50 fps and it still runs update at 15Hz, and more importantly, you still move at the same speed, say 4mph walking, not 4 * 5/6 = 3 1/3 mph walking.

So the user can set the fps at the fastest their PC can do consistently. and they get one render one input one update guaranteed each frame.  no tweening, no dropped frames.

##### Share on other sites
Keeping the current and previous states isn't as bad as you might think, and interpolation gives excellent results.

Personally I only keep the two states for things I render. My physics just runs like normal for example, but the thing that is responsible for drawing the object stores previous position and angle and I do the interpolation only when I render. Works great for me.

[Edit - Sorry, I see Kylotan has already made this point :)]

I have a template class to assist with this that stores the previous and current value and works for any type for which I provide an interpolate(const T &a, const T &b, float t) function. For example, float, Vec3, Quaternion etc.

In Caveman 3.0 I'm currently using a user defined frame rate limiter. update runs at 15 Hz. the user chooses a target FPS. The target FPS determines the frame time for the limiter. an accumulator accumulates frame times, and update consumes frame time in discrete chunks so it works out to 15Hz. update also scales all deltas based on FPS.
So you set it for 60 fps, and assuming your hardware can do 60 fps, it runs at 60 fps. knock it back to 50 fps and it still runs update at 15Hz, and more importantly, you still move at the same speed, say 4mph walking, not 4 * 5/6 = 3 1/3 mph walking.
So the user can set the fps at the fastest their PC can do consistently. and they get one render one input one update guaranteed each frame. no tweening, no dropped frames.

I've never personally experienced the problems you cite here, with dropped frames? I regularly test by putting something like Sleep(500) or whatever in my main loop and, while things obviously get a bit jerky, everything still runs at the same speed.

Could you clarify exactly what problem you are solving here? I'd be interested in making it manifest in my game so that I can understand better. How would one force your problem to appear?

Thanks.

##### Share on other sites

In Caveman 3.0 I'm currently using a user defined frame rate limiter.  update runs at 15 Hz.  the user chooses a target FPS.  The target FPS determines the frame time for the limiter. an accumulator accumulates frame times, and update consumes frame time in discrete chunks so it works out to 15Hz. update also scales all deltas based on FPS.

So you set it for 60 fps, and assuming your hardware can do 60 fps, it runs at 60 fps. knock it back to 50 fps and it still runs update at 15Hz, and more importantly, you still move at the same speed, say 4mph walking, not 4 * 5/6 = 3 1/3 mph walking.

So the user can set the fps at the fastest their PC can do consistently. and they get one render one input one update guaranteed each frame.  no tweening, no dropped frames.

Interesting approach! Is your article still valid? I don't see the accumulator here. Thanks.

Keeping the current and previous states isn't as bad as you might think, and interpolation gives excellent results.

Personally I only keep the two states for things I render. My physics just runs like normal for example, but the thing that is responsible for drawing the object stores previous position and angle and I do the interpolation only when I render. Works great for me.

[Edit - Sorry, I see Kylotan has already made this point :)]

I have a template class to assist with this that stores the previous and current value and works for any type for which I provide an interpolate(const T &a, const T &b, float t) function. For example, float, Vec3, Quaternion etc.

In Caveman 3.0 I'm currently using a user defined frame rate limiter. update runs at 15 Hz. the user chooses a target FPS. The target FPS determines the frame time for the limiter. an accumulator accumulates frame times, and update consumes frame time in discrete chunks so it works out to 15Hz. update also scales all deltas based on FPS.
So you set it for 60 fps, and assuming your hardware can do 60 fps, it runs at 60 fps. knock it back to 50 fps and it still runs update at 15Hz, and more importantly, you still move at the same speed, say 4mph walking, not 4 * 5/6 = 3 1/3 mph walking.
So the user can set the fps at the fastest their PC can do consistently. and they get one render one input one update guaranteed each frame. no tweening, no dropped frames.

I've never personally experienced the problems you cite here, with dropped frames? I regularly test by putting something like Sleep(500) or whatever in my main loop and, while things obviously get a bit jerky, everything still runs at the same speed.

Could you clarify exactly what problem you are solving here? I'd be interested in making it manifest in my game so that I can understand better. How would one force your problem to appear?

Thanks.

Hi, you are probably right. I was worried thinking in a scenario where a large amount of objects needs to be interpolated, but this is not my case anyways.

Edited by ArtLem