Quick answer: Tick Spawn on every replicated property in MultiplayerSynchronizer’s Replication Config. For event-driven state that pre-dates the join, send a custom snapshot RPC right after the peer connects.
Player joins midway. Their HUD shows everyone’s score as 0. Server has the actual scores; the synchronizer didn’t send them at spawn.
The Symptom
Late-joining peers see default values for properties that should reflect server state. Continuous changes after join replicate fine; pre-join state never arrives.
The Fix
MultiplayerSynchronizer:
Replication Config:
.score Sync: true Spawn: true
.health Sync: true Spawn: true
.team_id Sync: false Spawn: true # once at spawn, never updates
Spawn = true makes the property included in the spawn payload. Late joiners receive the value as part of the spawn replication.
Custom Snapshot RPC
# On the server
func _on_peer_connected(id: int) -> void:
var snapshot := {
"scores": scores,
"round": current_round,
"timer": round_timer,
}
rpc_id(id, "_receive_snapshot", snapshot)
@rpc("authority", "reliable")
func _receive_snapshot(snapshot: Dictionary) -> void:
# Apply on the client
scores = snapshot["scores"]
...
Reliable RPC ensures the new peer gets the snapshot exactly once. Apply on the client before showing the game.
Verifying
Start a game, advance state, connect a second peer. Late joiner should see the current state, not defaults. Test with various Spawn flag combinations.
“Spawn flag for state. Snapshot RPC for events. Late joiners catch up.”
Related Issues
For MultiplayerSynchronizer config, see synchronizer config. For MultiplayerSpawner, see spawner.
Spawn flag plus snapshot RPC. State arrives.