Delta Time Issue


#1

I’ve been struggling with jerky / stuttering sprite movement under SDL 2.0.9. Occasionally and for no obvious reason the delta time would either jump really low, or really high for 1 - 2 frames, causing some jerky movement. I finally decided to try an older version of SDL (2.0.4) just to see if it was the version, and surprisingly, it seemed to have fixed the issue. I’d like to continue to use 2.0.9 though. Anyone else have this issue under 2.0.9?


#2

Can you explain how you implemented delta time or maybe show some code ?.
Are you using vsync ?


#3

Is this on Windows?
Try passing SDL_INIT_JOYSTICK to SDL_Init(), that works around a bug in 2.0.9 that can cause frames to take longer than they should.
(Yes, this helps even if you don’t have any joysticks or don’t plan to support them in your program)


#4

This seems to have fixed the issue! Thanks! There is still an occasional jump in delta time (from 16.xxx to somewhere in the 20’s), but not nearly as frequent as it used to be. This is probably due to my code, so I"ll try to optimize it where I can. Thanks a bunch!


#5

Glad it works!

@slouken @icculus with this bug and macOS Mojave OpenGL issues being fixed/worked around in hg, I think it would make lots of sense to release 2.0.10 soon, so people don’t run into the same problems again and again :slight_smile:


#6

@Daniel_Gibson @Smiles So as I mentioned the stutter is significantly less than it used to be, but it’s still frequent enough to be a problem. I’m providing a link to the GIT for this in hopes you can spot something obvious. It’s basically a 4 paddle pong game where you control all 4 paddles (with the mouse) and the goal is to keep it going as long as you can. However when that delta time jumps it causes a stutter in the balls movement, which can cause issues. I calculate the delta time in the Game.h/.cpp class under the UpdateDelta() function. I’ve tried using chrono and SDL’s built in GetTicks() to achieve this and they both yield the same results. Also as you can see I am using Vsync, but the problem persists even without it.

https://bitbucket.org/CGunn86/pong-game/src/master/

If you need me to provide a gameplay video showcasing the stutter and what the game looks like, then let me know and I’ll do that.


#7

So one thing I did notice is you have vsync enabled. May I ask is this working ?

If this is working as intended then you should not have to calculate delta time as you know you frames are locked at 60. Try using a constant value instead like the result of 1 / 60.

This may not be the greatest idea if your game is dropping frames but its worth a go.


#8

@Smiles Yeah Vsync is working, but not everyone has the same refresh rate, so the delta time calculation is to make sure the game’s speed/pace is the same for everyone. I use a 60hz monitor so I get 60fps, but others might play on 120 or 144. So if they’re playing on 120 or 144 and I fix my delta time by doing 1.0f / 60.0f then won’t that not work right since they’re not locked at 60?

EDIT: And yeah, if I’m dropping frames then it’s probably not a good solution, still gonna have a micro stutter once in a while when that happens.


#9

Good point. You could always roll you own frame limiter which may benefit in this case if people play with multiple framerates.

Still looking through code.

Whats the print out of delta each update ?
Does it vary much


#10

On average:

16.529332
16.951465
16.488934
16.596077
16.808022
16.797190
16.606908
16.668677
16.612178
16.491568
16.670141
16.674239
16.668677
16.785188
46.631311
14.686820
10.976034
10.976327
16.652869
16.756792
16.603688
16.642623

You can actually see the stutter right there when it jumps to 46. But otherwise no, it doesn’t vary much at all. Stays right at 16.xxx until it stutters.


#11

What about doing a running average ?
Keeping total count of delta times.
Keeping total count of updates.

Your new delta time is 1 divded by the other.
Hopefully 1 outlier wnt make much of a differeance


#12

hmmm not really sure I know what you mean.


#13

//calculate delta time
totalDeltaTime += deltaTime;
totalUpdates +=1;

newDeltaTime = totalDeltaTime / totalUpdates;

example
[0]
deltaTime = 10;
totalDeltaTime = 10;
totalUpdates = 1;
newDeltaTime = 10 / 1 = 10;

[1]
deltaTime = 12;
totalDeltaTime = 22;
totalUpdates = 2;
newDeltaTime = 22 / 2 = 11;

[100]
deltaTime = 50;
totalDeltaTime = 1050;
totalUpdates = 100;
newDeltaTime = 1050 / 100 = 10.5;

even tho we got something 5 times bigger then what we expect it only caused a slight increase.


#14

Guess I can try it and see. What are you storing in the array though? Like what is [0], [1], [100].what variable is this?


#15

[0][1] etc where only to show current frame

you will need 3 new vars;

totalUpdates;
totalDeltaTime;
avgDeltaTime;

while(isGameRunning) {
    // calc deltatime;
   totalDeltaTime += deltaTime;
   totalFramesElapsed += 1;
   
   avgDeltaTime = totalDeltaTime / totalFramesElapsed;
}

#16

ok I’ve updated my code in the GIT, trying it now. So the delta time now doesn’t jump and stays in the 16.xxx range forever, but there is still a micro stutter happening, not quite as obvious now, but it’s still noticeable.


#17

It seems you could be losing precision on some of your entities.
This may cause a stutter. Off by a pixel.

void Ball::Update()
{
	m_posX += static_cast<int>(m_velocityX * Game::avgDeltaTime);
	m_posY += static_cast<int>(m_velocityY * Game::avgDeltaTime);
}

Try changing m_pos to be a vector of floats and only cast them at drawing time.
This may apply to other entities also.


#18

@Smiles In release mode this average delta time solution seems to be working just fine.Thanks! However I have one concern. Won’t totalUpdates eventually grow too large and cause an issue?


#19

Hmmm you could always set the count back to 1 and the average back to 0.1666 or whatever after sometime.

Using an int32 should be ok for 400 days non stop if my maths are right for 60fps.


#20

@Smiles Oh well if it’s 400 days then that’s plenty, I don’t expect anyone to run it that long! But also need to consider that people use 120hz and 240hz monitors. I am not locking the game at 60fps.But even at 240 it would last 100 days, so I guess that’s not an issue. And it’s not being stored in an int32, but rather a double.

So yeah, I think as long as it won’t max out and wrap for at least a couple of hours, then I should be fine. I don’t expect myself or anyone else to be running my game that long, hah.