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.