You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a fix for clients remaining desynchronized from the server when freezing / pausing their games.
When freezing or pausing the game the network-time.gd handles this pause when it detects a large time has elapsed since the last update.
EXPLAINATION
When pausing or freezing the network timers continue to update so our network clock stays synced and our reference clock requires little catchup. However, our _tick variable won't be automatically updated (this is what actually drives the multiplayer).
CONSEQUENCES OF ISSUE
The result is a client who thinks they are in the past, this has two consequences:
The server will interpret the clients inputs as old (older than the max allowed history) and ignore them. The player will then be frozen.
The client will interpret server updates as being in the future and wont run them until its _tick variable has "caught up". The effect is that a client sees server updates with a delay equal to the time frozen/paused.
This does not just resolve itself and currently breaks the client until they disconnect/reconnect.
FIX DESCRIPTION
This commit adds a line which updates the _tick to the current network time after a pause is detected. This PR doesn't clear the rollback buffers and will mean that potentially some client inputs will still be sent with an old _tick (not a big deal as new inputs will now have the updated _tick but it would be nice to add).
I first noticed this issue when I paused by games and noticed my client never "resyncs" with the server, in actuality its clock was synced but its _ticks was not. To reproduce / test this issue our yourself add this code to your game.
I tested this PR by adding it to the player.gd script in the multiplayer-fps example.
func _process(delta: float) -> void:
if Input.is_key_pressed(KEY_T):
# Uncomment below to test freezes
OS.delay_msec(2000)
# Uncomment below to test pauses
#get_tree().create_timer(2.0, true, false, true).timeout.connect(get_tree().set_pause.bind(false))
#get_tree().set_pause(true)
Then create to instances of the fps game, one as host, and other as client. As the client press T and introduce delay until the timer becomes permanently behind and becomes unresponsive.
Thanks a lot for the research and the PR @Riordan-DC! Am I correct in assuming that this also fixes #332?
The pause detection logic only runs when launched from the editor atm, I think we could remove that condition, and make the pause threshold configurable, instead of being hardcoded at 1 second. I'll add these changes soon!
Thanks a lot for the research and the PR @Riordan-DC! Am I correct in assuming that this also fixes #332?
The pause detection logic only runs when launched from the editor atm, I think we could remove that condition, and make the pause threshold configurable, instead of being hardcoded at 1 second. I'll add these changes soon!
yes thats correct it fixes that issue and yes I think that pause/freeze logic would be good even when not in the editor to handle people who minimize or otherwise freeze their game.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ISSUE DESCRIPTION
This is a fix for clients remaining desynchronized from the server when freezing / pausing their games.
When freezing or pausing the game the network-time.gd handles this pause when it detects a large time has elapsed since the last update.
EXPLAINATION
When pausing or freezing the network timers continue to update so our network clock stays synced and our reference clock requires little catchup. However, our _tick variable won't be automatically updated (this is what actually drives the multiplayer).
CONSEQUENCES OF ISSUE
The result is a client who thinks they are in the past, this has two consequences:
The server will interpret the clients inputs as old (older than the max allowed history) and ignore them. The player will then be frozen.
The client will interpret server updates as being in the future and wont run them until its _tick variable has "caught up". The effect is that a client sees server updates with a delay equal to the time frozen/paused.
This does not just resolve itself and currently breaks the client until they disconnect/reconnect.
FIX DESCRIPTION
This commit adds a line which updates the _tick to the current network time after a pause is detected. This PR doesn't clear the rollback buffers and will mean that potentially some client inputs will still be sent with an old _tick (not a big deal as new inputs will now have the updated _tick but it would be nice to add).
I first noticed this issue when I paused by games and noticed my client never "resyncs" with the server, in actuality its clock was synced but its _ticks was not. To reproduce / test this issue our yourself add this code to your game.
I tested this PR by adding it to the player.gd script in the multiplayer-fps example.
Then create to instances of the fps game, one as host, and other as client. As the client press T and introduce delay until the timer becomes permanently behind and becomes unresponsive.