Variable dt causes game to run twice as fast (DEF-3146) (SOLVED)

I stopped investigating this once I activated variable dt for my game and I perceived it to be the same speed on my android phone and windows build.

But, I noticed that with variable dt unchecked (and all scenarios = 60fps), the game went a LOT faster on Windows than Android.

@britzl Hi! Sorry for insisting, but did this get an issue number? It’s pretty serious and reading the forum I see other people are having seemingly similar timing issues:

Additionally, a colleague noticed that there are issues even when variable dt is turned off (animations with go.animate() go too slowly, while the dt we get in update goes at the right rate). I’ve yet to confirm this, though (I’ll only get to Win PC tomorrow). Might have been just frame skips.

1 Like

When variable_dt is not checked the engine will rely on hardware vsync for each frame. The engine also assumes as a refresh rate of 60Hz.

With variable_dt checked the engine will update as fast as possible and calculate dt accordingly. This means that the size of dt can vary greatly between two frames which can be a problem for physics simulations for example.

From what is described in this thread and the fact that the issue seems to be isolated to Windows, there might be some precision issue with the dt calculation when running with variable_dt on Windows. Created issue DEF-3146 for this.

It is important to remember to use dt in your script update functions correctly. With variable_dt your update functions will most likely be called much more often, but with a smaller dt, than when running your game without variable_dt

3 Likes

Don’t be sorry. You’re right to insist! This is a critical issue and something we need to look into. Windows seems to be the problematic platform, and if I recall correctly there were differences between version (Win 7 and 10).

Johan created a ticket that hopefully will be picked up as soon as possible.

5 Likes

Wait, does that mean that checking variable_dt should turn off vsync? That doesn’t happen on OS X and that probably shouldn’t happen.

The way I understood variable_dt is that when it’s turned off:

  • The game displays frames on vsync
  • update() is called with a dt always equal to 1/update_frequency
  • update() might not be called every frame if the screen is drawn faster than update_frequency.
  • update() might be called twice for a frame if the screen is drawn slower than update_frequency.

And when variable_dt is turned on:

  • The game displays frames on vsync
  • update() is called with a dt based on diffing system time.
  • update() is only called exactly once per frame.

Did I understand correctly?

In which case, what happens in the following scenarios?

  1. variable_dt off, update_frequency = 60, user’s display is 50Hz? Does the game run 1.2 times slower or does update() get called twice per frame once every fifth frame?
  2. variable_dt off, update_frequency = 30, user’s display is 60Hz? Does update() only get called once every other frame?
  3. variable_dt off, update_frequency = 60, user’s display is 60Hz, but his GPU/CPU is too slow and sometimes misses the vsync. Does the game still assume it’s running smoothly at 60Hz and the frame skips cause the animations to slow down? Or does it call update() twice after a missed vsync?
2 Likes

With variable_dt turned off the engine will set the GL swap interval to 60 / update_frequency (OpenGL set swap interval) and will only call script update() at each display refresh, with dt set to 1/update_frequency

With variable_dt turned on the engine does not care about vsync at all (vsync can be enabled/disabled in GPU drivers settings which we have no way of controlling) and will just update as fast as possible (calling script update() each time) with dt being calculated using platform timing functions . This might result in screen tearing (screen tearing) and big variations in dt if for example a fast frame is followed by a frame doing lots of heavy computations.

Defold does not have any decoupling between an engine update and calling script update() and we don’t skip frames to compensate for mismatching refresh rates, we rely entirely on hardware vsync (e.g. the combination of the set swap interval and the driver vsync-settings). A caveat; you can use set_vsync message to achieve software vsync in defold.

Perhaps the documentation around this should be improved. Questions about, variable_dt and vsync etc. pop up every now and then here on the forums. I’ll make a note of it!

Correct me if I’m wrong or missed anything @sven @Mathias_Westerdahl @Andreas_Tadic.

3 Likes

Yes, your answer is probably the best summary of the impact of variable_dt on and off that we have anywhere.

I’m using a 165hz monitor with nvidia g-sync, does this also have an effect? I have yet to sit down in my reading lounge with these last explanations so I’m a bit confused.

Edit: Just moving the running dmengine.exe from my 165hz monitor to my 60hz monitor speeds up and slows down the game immensly, so yes, it does have an effect :slight_smile:

2 things I’m still confused about now is:

  1. Is there a performance hit for settings msg.post("@system:", "set_vsync", { swap_interval = 0 } ) ? I tried that, and that removes the “sped up” effect on my 165hz monitor, both monitors seems to act the same.
    This is with variable dt unchecked btw.

  2. What settings gives the most similar/consistent experience between my dev pc and slower mobile phones that might drop below 60 fps here and there? I suppose the answer is dependant on what I define as similar experience…

Is it correct to assume that with variable dt, the game could actually slow down due to frame drops but not let the player “miss” anything, but without variable dt, the game could drop frames and the choppy gameplay could make it harder for the player to react to things, essentially “missing” stuff happening between the frames?

The way I understood it:

WITHOUT variable dt, the game will slow down, but not let the player miss things. WITH variable dt, the game will run at constant speed, but frame skips might make the player miss things

Without variable dt, there is no way to make sure the game runs at the same speed if the display refresh rate is not 60Hz (Which makes this option a no-go for me), UNLESS you use swap_interval = 0, which updates the game on a timer, ignoring vsync (which I believe might cause tearing).

With variable dt, you rely on whatever the driver setting for vsync is and the game will always run at the same speed. Also physics updates might be imprecise due to variable dt.

There is no performance penalty for swap_interval = 0 except your FPS will be fixed at update_frequency.

2 Likes

This makes it a bit clearer for me, but I’m not sure I’m 100% there.

I don’t want tearing, and I don’t want imprecise physics.

@devs, documentation suggestion, maybe have like a simple table with different approaches and their pro’s/con’s, and a comment on different types of games that would benefit from which type of approach?

4 Likes

I’m working on my game on Windows, which runs the game slightly faster than on my Galaxy S7.

I noticed that if I just bump up the timestep on my collection proxy, the game feels a lot better (like on my computer), so I think I’m going to lower the timestep instead during development, adjust gameplay feel accordingly, and then put it to 1.0 when finishing up.

It’s not hard to do since I’m already tweaking timestep due to gameplay features. Only drawback off the bat is that the ratio between “full speed” and slowed down events are off if I keep switching the full speed timestep value and not the others.
The “others” being for example slow down on player death or dramatic events in game.

1 Like

That is a great idea.

3 Likes

In the meantime, I made this work-around to the variable_dt on Windows bug. It measures game time and real time for an interval of 1 second and tells you the time step you should use in your collection proxies.

2 Likes

Hi! Any news on this? @Johan_Beck-Noren? @britzl? It’s a pretty serious bug and my workaround is not perfect.

1 Like

We added ticket DEF-3146 for tracking this issue, but no progress so far I’m sorry to say.

As a first step we talked about better documenting how vsync, variable_dt and monitor refresh rate play together in Defold.

As the problem is described in this thread it definitely seems like a problem with how we measure time, perhaps too low os timer resolution. We are working on it!

8 Likes

Solved in Defold 1.2.126

4 Likes

I’m making a Facebook Instant game. When using go.animate on iOS devices on battery saving mode (and thus locked to 30fps) the animations take twice as long. When “Variable Dt” is ticked in the project settings they appear to take the correct amount of time, but the animations are choppy.

Equally, on my external monitor the game runs at 75 fps and the animations are too fast when “Variable Dt” is unticked.

Could this be related to the discussions in this thread, or is this expected behaviour? If so, what’s the correct way to deal with this? I’m using Defold 1.2.140.

We will release support for variable refresh rate screens soon. Most likely in 1.2.142, in two weeks.

Not sure about iOS battery saver mode though. @Johan_Beck-Noren?

3 Likes

variable_dt should be a solution for most cases since it measures actual time elapsed for the time step used. Can you describe more how the animations are choppy? Choppy as in unstable just 30fps-choppy?

1 Like

Amazing!

Choppy as in skipped frames; the animation is stable but not smooth.