From c72bdfe7ab96f57e6074d5ac48a728abd8cbdccd Mon Sep 17 00:00:00 2001 From: chris-ruecker Date: Wed, 26 Nov 2025 18:18:50 +0100 Subject: [PATCH] fix: TickInterpolator records state after RollbackSynchronizer display state Connect TickInterpolator to NetworkRollback.after_loop instead of NetworkTime.after_tick_loop when rollback is enabled. This ensures interpolation state is recorded AFTER RollbackSynchronizer applies display state, fixing jittery remote player movement on the host. The issue occurs because both TickInterpolator and NetworkRollback connect to after_tick_loop. If TickInterpolator runs first, it records state before the rollback loop completes and display state is applied. This causes the interpolation target to be stale, resulting in visual jitter for remote players observed on the host. Falls back to original after_tick_loop behavior when rollback is disabled. --- addons/netfox/tick-interpolator.gd | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/addons/netfox/tick-interpolator.gd b/addons/netfox/tick-interpolator.gd index dfb5666e..9aa10e76 100644 --- a/addons/netfox/tick-interpolator.gd +++ b/addons/netfox/tick-interpolator.gd @@ -108,11 +108,20 @@ func _get_configuration_warnings() -> PackedStringArray: func _connect_signals() -> void: NetworkTime.before_tick_loop.connect(_before_tick_loop) - NetworkTime.after_tick_loop.connect(_after_tick_loop) + # Connect to after_loop instead of after_tick_loop to ensure state is recorded + # AFTER RollbackSynchronizer applies display state, fixing jittery remote + # player interpolation on the host. + if NetworkRollback.enabled: + NetworkRollback.after_loop.connect(_after_tick_loop) + else: + NetworkTime.after_tick_loop.connect(_after_tick_loop) func _disconnect_signals() -> void: NetworkTime.before_tick_loop.disconnect(_before_tick_loop) - NetworkTime.after_tick_loop.disconnect(_after_tick_loop) + if NetworkRollback.enabled: + NetworkRollback.after_loop.disconnect(_after_tick_loop) + else: + NetworkTime.after_tick_loop.disconnect(_after_tick_loop) func _enter_tree() -> void: if Engine.is_editor_hint():