Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Let's say we have a standard gameloop like this, in pseudocode:

while (true) {
    dt = GetDeltaTime();
    Update(dt);
    Render();
}

Here Update(dt) either uses a true variable timestep, or it determines how many cycles of a fixed timestep physics loop to execute based on dt.

Now say we have the common case where we have mostly constant framerate except for infrequent single-frame hiccups, so let's say we have dt values like

1/60, 1/60, 1/60, 1/6, 1/60, 1/60, ...

By the time our GetDeltaTime() detects the larger timestep in the fourth frame, we have already rendered and presented the fourth frame! So one frame will already have been rendered with a wrong (too small) timestep no matter what we do.

So if we now use the larger dt=1/6 to render the fifth frame, my understanding is that we artificially create a second frame where a wrong timestep is used, this time a too large one. I wonder if this problem is acknowledged anywhere. Wouldn't it be better, say, to use the averaged dt over the previous few frames to combat this?


Here are some pictures to illustrate what I mean. I use the example of an object moving along a fixed axis with a constant speed, and using a variable timestepping scheme. The problem is essentially the same with fixed timesteps, though.

The plots have time on the x-axis, and the object position on the y-axis.

Let's say the object moving at 1 unit/s, and framerate is 1 Hz. This is the ideal situation.

perfect

Now let's say we have a frame where the time interval is 2 instead of 1. With a classical dt-based scheme, we get this:

dt-var

So we have one frame where the velocity is perceived too low, and one where it is perceived too high and which corrects for the velocity in the previous frame.

What if we instead, say, always use a constant (or very slowly changing) dt? We get this:

dt-const

The perceived velocity seems smoother using this approach to me. Of course, the object position is now not the "true" one, but I think humans perceive abrupt changes in velocity more clearly than such small positional offsets. Thoughts?

UPDATE:

At least Ogre can do this: http://ogre.sourcearchive.com/documentation/1.6.4.dfsg1-1/classOgre_1_1Root_1f045bf046a75d65e6ddc71f4ebe0b2c.html So I guess I just got downvoted for people not understanding my question, which is rather frustrating.

share|improve this question
    
Is there some actual code you have in your project which meets this problem? If so it might be easier to ask it in a contextual question rather than an abstract pseudocode. –  Blue Mar 7 at 10:20
    
It's pretty much a conceptual question, so I don't think that would help. –  eriatarka84 Mar 7 at 12:27
2  
I don't understand the issue you describe. Each frame is a discrete unit (a step) with an integral index and it is on the display for a real amount of time so your graphs are all wrong, it should be a steps graph. like this: a correct frame / time steps graph –  Zehelvion Mar 7 at 13:17
    
@ArthurWulfWhite hit the nail on the head. Your time step adjusts as needed by your physics when using a deltaTime model. Your graph would still be like your first image but your timestep would be 3 and so dT = 2 and your x:y ratio in this graph of 1 unit to 1Hz would be 2 units to 2Hz so your concept is wrong. This is why I asked if this had some real project example as then we could understand the application of your problem. –  Blue Mar 7 at 13:47
1  
This is a bog standard game loop that you have in pretty much every game out there. What about it isn't a "real world scenario"? I don't know what you mean by interpolating. The plots show a standard variable timestep scheme. –  eriatarka84 Mar 7 at 22:15

3 Answers 3

To expand a bit on my comments in Shadows In Rain's answer:

If you're using variable timesteps, you shouldn't encounter this issue at all, unless you still cut it down to n updates in some way.

If you're using fixed timesteps, then you might hit that "stuttering" problem purely based on timing.

The problem is that - based on timing - you might draw a scene right before updating or just after an update has happened. Due to this animations (or movements) might not appear as fluent as they should, because they're essentially not constant at all.

Imagine a simple update loop like the on in Shadows In Rain's answer:

tick_rate = 1.0 / 66; // 66hz
adt = 0.0; // accumulated delta time
while(!quit) {
    adt += GetDeltaTime();
    if(adt >= tick_rate) {
        adt -= tick_rate;
        Update(tick_rate);
    }
   Render(adt);
}

There's nothing wrong with this code and it's running perfectly fine. Also, based on framerates and the number of updates per second, this will be as smooth as it can get.

However, as you lower the rendering framerate, you might suddenly notice stuttering, even if you're rendering at 60 FPS.

For simplicity, let's assume your game updates its state 60 times per second and your rendering is limited to 60 FPS as well (slowing the loop down to this rate, either through vertical synchronization or by being busy doing the actual rendering).

So you've got a ball that is moving at 1 pixel per update. That means, in a perfect world, it should move 60 pixels per second, one pixel per frame.

So theoretically, every 16.67 ms the ball moves by 1 pixel. As long as this is true, the animation will appear as smooth. However, let's assume in one iteration your accumulated time is only 16.60 ms. This means there won't be any update.

The result: The ball won't move for one frame (since no update happened). The next frame there might be two updates happening at once (since the accumulated time is now 34.03 ms) and now the ball moves by two pixels between frames.

Things like this might appear as some kind of "micro-stuttering". This can be hard to notice, but depending on your actual game layout it might be pretty obviousy.

Can you fight it? Yes, but it's a bit tedious based on how your draw/update your game.

You'll have to keep the previous screen's state (just taking a screen capture won't be enough; this isn't about blending two images).

In our example, you always keep the position of the ball during the last calculated frame.

To determine the actual position for drawing, you'd then use something like this:

drawing_x = old_x + (current_x - old_x) * f;

Where f is a factor between 0 and 1 based on how much time is in your accumulator:

f = adt / tick_rate;

So, the less time left till the next update, the further your ball's position will be drawn.

This will essentially introduce a one frame lag, which should be hardly noticeable. But at the same time it should help smoothen out your perceived framerate.

Keep in mind that there might be other factors causing minor stutters as well, e.g. the actual window manager presenting the window or some driver or hardware feature (like "adaptive vertical sync").

Before I finish, I'd like to get back to one statement from above: just taking a screen capture won't be enough; this isn't about blending two images

Actually, this isn't 100% true. If you can, you can also include some kind of motion/movement blur. This should also help with hiding slight stutters, especially for tiny movements, since it will be a lot harder to follow exact outlines or movements. Of course this is not an option for every use case, but it might be something to think about.


Update since you've added those graphs:

I think it's important to note that you'll have to identify where you're running slow and/or causing delays so you no longer update just-in-time.

In your second graph, you obviously take too much time to update your game logic, so you miss out one frame.

To fight this, you could drop a frame (usually described as frame dropping; pretty popular for emulators), or you try fighting this by constantly updating your accumulator, even while doing the updates (it's important to note that on very fast computers you'll have to ensure that you don't always just add 0 due to rounding or whatever):

tick_rate = 1.0 / 66; // 66hz
adt = 0.0; // accumulated delta time
while(!quit) {
    adt += GetDeltaTime();
    if(adt >= tick_rate) {
        adt -= tick_rate;
        Update(tick_rate);
        adt += GetDeltaTime(); // this is an additional update of the accumulator
        // here you'd want to count the iterations to ensure
        // you don't update forever and can't catch up!
    }
   Render(adt);
}

Of course this isn't possible for dynamic timesteps, so there'll always be some slight delays or lags. Don't think there's any effective way to fight that in all possible situations.

share|improve this answer
    
Thanks for the detailed answer. I'm convinced that your assertion that using variable timestep eliminates this problem is false. The one-frame lag is unavoidable, no matter how you do your updates. You describe temporal aliasing, which is important to keep in mind but a different issue. Look at the original post, I added some pictures to illustrate the variable timestep case. –  eriatarka84 Mar 7 at 12:25

Do not rely on framerate if you want truly fixed timesteps for game logic, physics, etc. To keep rendering alive between updates, roughly extrapolate game state.

tick_rate = 1.0 / 66; // 66hz
adt = 0.0; // accumulated delta time
while(!quit) {
    adt += GetDeltaTime();
    if(adt >= tick_rate) {
        adt -= tick_rate;
        Update(tick_rate);
    }
    // remaining adt now means how rendered image must be ahead of game state
    // use it as extrapolation factor
    Render(adt);
}

Relevant: Fixed time step vs Variable time step

share|improve this answer
    
You didn't read the question carefully. I did mention that Update() may already be implemented in terms of a fixed timestep. This doesn't really relate to the frame lag issues that's the core of my question. The main point is: we don't know the time to extrapolate with until AFTER we have rendered the frame. –  eriatarka84 Mar 7 at 9:49
    
You can't really get rid of this completely. All you can do is take the leftover time in the accumulator (in this code adt) and use that to interpolate everything for the last two frames. So you'll essentially end up with one frame of lag, but it should appear smoother. –  Mario Mar 7 at 10:02
    
What wrong with adt? –  Shadows In Rain Mar 7 at 10:03
    
Nothing wrong with that. The code is perfectly fine. But based on when you render the scene (e.g. 1 ms just before or after an update tick), you might skip updates. This isn't noticeable depending on your framerate and update rate. I'm going to expand on this in a moment. –  Mario Mar 7 at 10:04
    
I outline a different approach from just accumulating frametimes in the OP. I have also added pictures. I hope this makes my point clearer. –  eriatarka84 Mar 7 at 12:46

I know exactly what you mean. Delta time gives us how much time to add to the simulation so that in-game seconds match real life seconds over time. However, it doesn't give us the time at which the frame is shown to the player, as rendering on the upcoming frame could overrun and be displayed a frame late.

In the delta time graph you're back where you should be after two frames. In your possible solution you're always one frame behind after the drop. A faster machine would update more than a slower one and therefore be at an advantage in multiplayer games - you would be able to move further per real life second if you didn't drop frames for example.

The only solution is to vsync, use a fixed update interval, and guarantee your game can render in a frame. This is why old (70's/80's) arcade games were smoother than current video games.

share|improve this answer
    
You're right that in the possible solution, you would lag behind "real time", whatever that means, a bit. I think this doesn't matter, except for a low-latency multiplayer situation. My idea is that the smoother change of the object velocity in my proposal leads to overall higher perception of smoothness by the player. That the object positions are ever so slightly off from where they should be in a completely physically correct simulation doesn't matter as much as the perceived smoothness, in my opinion. –  eriatarka84 Jun 26 at 8:58

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.