Vsync and dt

One of our player has reported a very high speed in the game, like it is running 3x the normal speed. It turns out that it has a monitor with refresh rate of 144Hz, and a very powerful graphic card (I would say). I guess the problem is this higher frequency but I was expecting Defold to handle this without any problem. And probably it is and I have just chosen the wrong settings.

I would like to have the update functions to be called each frame with a variable dt, in other words dt should be equal to the time since the last update. In the project settings I have set Vsync (checked) and I have 0 in Frame cap. Are these the right settings?

I have read the manual here https://defold.com/manuals/project-settings/ but it is not clear to me…

Ciao!

1 Like

I have the same issue when I do html5.

I have a 144 Hz and a powerful graphic card.

Try Vsync (unchecked) and Frame Cap = 0? This works for me on a monitor with similar refresh rate…

Yes, thanks! On my mac the game runs fine also with these settings, but I have not a 144Hz monitor. So I would like to understand what I am doing… :slight_smile:

EDIT: I found more information at the end of the same manual. Now I would say that both
(i) Vsync checked, frame_cap = 0
(ii) Vsynd unchecked, frame_cap = 0
should works fine also on a 144Hz monitor.
Maybe the player reporting this problem has more than one monitor with different frequencies? And Defold read the frequency from a 60Hz monitor while the game were running on a 144Hz monitor? Perhaps (ii) should work better in this scenario?

Any help?

This is highly possible. Maybe you can use DesfOS to query screens and frequency ( Query displays section). I think @Pkeod has better answer to this.

I think the issue here is not vsync per-se, but variable refresh rate systems like FreeSync or G-Sync. I’ve had users report the game being sped up as well and most of the cases, telling them to disable FreeSync as a workaround solved the speed-up.

What’s happening is that Defold tries to round all the dt’s up to 1/display’s_refresh_rate. With a VRR display, there is no refresh rate, refresh rate detection will fail and it will default to 60Hz. If the frames show much faster than that, the game will go faster.

I’ve also had spurious situations where Defold would detect the refresh rate wrongly (on a non-VRR display) and a restart of the game would fix it.

Thanks @dapetcu21.

But should VSync not-checked treats also the case where there is no refresh rate and all the other situations you described? dt should be computed via a timer from the last update and the game should have a high frame rate but with the right speed.

But probably there is something I have missed from your answer…

You are right. It should, but it is not. The reason is that the physics system needs to be updated in constant steps and, for now, rendering timing is linked to physics update timing. I saw that decoupling these is planned in the roadmap, which would probably solve this issue as well.

So you are saying that Defold is not respecting the behavior described in the manual about dt? I understand the physics must update at constant steps, but we don’t have physic_update, BOx2D is updated internally

It is most of the time, but it seems to fail for some reason with VRR displays in particular.

We shipped Interrogation with vsync = 0 and, from testing, that seemed to cause the least issues. Also, it doesn’t actually mean that vsync is disabled. If the user configured it in their GPU driver settings, it will still wait for vsync. Also, I think (not sure) on macOS it also still waits for vsync.

Thanks so much! So I will keep vsync = 0 and hope for the best! But I think Defold definitely needs better support for desktop. In particular this player is a gamer, I would say a professional gamer if these words have any meaning…

So, what I think it’s happening is that:

at 60Hz, with vsync = 1, if the game skipped a frame, you’ll still get dt = 0.1666
at 60Hz, with vsync = 0, if the game skipped a frame, you’ll get dt = 0.3333, but the way you get to this number is as such: round(real_timer_based_dt * refresh_rate) / refresh_rate (for physics step reasons). Without VRR, this is perfectly correct. A non VRR display’s real_timer_based_dt is guaranteed to be approximately a multiple of the refresh rate.

Yes, I see, thank you for the explanation. Your equation should work also for VRR display but for some reason it isn’t.

No. It can’t possibly work for VRR displays if you round that up because on a VRR display the frame interval can be any arbitrary number. Rounding it up or down or altering that value in any way will make the game go faster or slower.

On non VRR displays the rounding is not a problem
a) Because the interval is almost rounded anyway, so the error is small
b) Because over time, the errors tend to cancel out.

You are right. So decoupling physics from game object updates is really needed here. So that one can pass real_timer_based_dt directly to update without any rounding. Is it so?

1 Like

Have you managed to resolve this issue for the player that reported it? I think I ran into either the same or similar issue:

When running the One-way platforms example with 144Hz refresh rate, the character jumps much lower, and it does seem to run a tiny bit faster, though not nearly 3x.

I’ve experimented with various settings and it seems the only combination that produces the intended jump height is Vsync off and a 60 frame cap.

For html5 builds, the jump height is correct whenever VSync is turned on, though it also causes a significant speed-up unless frames are capped at 60.

Switching my monitor to 60 Hz unsurprisingly fixed the issue across the board, unless I capped frames below 60. At that point the character would jump three times as high.

I only have one monitor and I’m not sure if I have FreeSync or G-Sync active. I tried to deactivate it, but I couldn’t find the option in the NVidia control panel, which seems to suggest it’s not supported on my setup, but who knows? It’s way too late for me to delve into this, but I may be able to confirm this tomorrow.

1 Like

Hi!

I am not sure since I haven’t sent the new build to the player with the issue. At the end I have decided to go with: vsync off, and frame cap 0. (I have almost forgot why this seemed to me the best options… sorry.)

However in certain situations (for example when resizing the window) dt is extremely large. This is not a problem if you use ONLY go.animate to move things around on screens. But, when you use some kind of “poor man physics” ( something like: x = x + v * dt) then you need to cap dt from above otherwise you may get weird results. This is not surprising since a line like x = x + v * dt is just a discrete approximation of a differential equation and you want dt to be small enough.

Hope this make some sense…

1 Like

It does, I think. Normally I’d just cap the frames at 60 and go on with my life, but I happened to play the old GTA games recently and cursed at the developers because disabling their 30 frame limit breaks the game, and I really don’t want to do the same mistake myself.

That should work. Thanks for the suggestion!

BTW, you mentioned you don’t have a 144 Hz monitor so you can’t test the issue yourself - I could help out, if you want. Of course, that’s assuming that the issue your player ran into would happen to me too.