fix: TickInterpolator records state after RollbackSynchronizer displa… #539
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.
Hi, i am currently creating a game, and am using netfox for netcode.
During testing, i noticed that the player connecting as client to the game saw the remote player's movement very smoothly.
But, on the hosts side, the movement of the clients character was slightly jittery. I asked claude to check if he could find the issue, and he came up with the solution below, which seems to have fixed the issue for me.
I don't quite understand the code of netfox, but maybe you can determine if this is a valid issue/fix.
Problem
When using TickInterpolator with RollbackSynchronizer, remote player movement appears jittery on the host, even with constant input (e.g., holding
a direction key). The client observing the host sees smooth movement, but the host observing the client sees stuttery/jittery motion as if discrete
tick updates are visible.
Root Cause
Both TickInterpolator and NetworkRollback connect to NetworkTime.after_tick_loop:
The execution order depends on signal connection timing. If TickInterpolator runs first:
Why host→client is jittery but client→host is smooth:
display state. Mismatch = jitter.
Solution
Connect TickInterpolator to NetworkRollback.after_loop instead of NetworkTime.after_tick_loop when rollback is enabled:
func _connect_signals() -> void:
NetworkTime.before_tick_loop.connect(_before_tick_loop)
if NetworkRollback.enabled:
NetworkRollback.after_loop.connect(_after_tick_loop)
else:
NetworkTime.after_tick_loop.connect(_after_tick_loop)
This ensures state is recorded after the rollback loop completes and display state is applied.
Backwards Compatibility
Falls back to original after_tick_loop behavior when rollback is disabled, maintaining compatibility for non-rollback use cases.