Jump to content
  • Advertisement
Sign in to follow this  
ArtLem

Avoid game state interpolation with fixed time step

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
Share on other sites
Advertisement

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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!