Tutorial

Simple state sync

Keep player positions aligned, and catch late joiners up with a snapshot.

1. Spawn & own an entity

Set an entity's state to create it — you become its owner. Key it by your player id.

var my_id := MultiplayerService.player_id
MultiplayerService.set_entity_state(my_id, { "x": 120, "y": 80 })

2. Patch as you move

Send partial updates; throttle them (e.g. ~15/sec) to stay under the rate limit.

MultiplayerService.patch_entity_state(my_id, { "x": new_x, "y": new_y })

MultiplayerService.entity_state_changed.connect(func(id, _patch, full):
    move_dot(id, Vector2(full.x, full.y)))

3. Handle the late-join snapshot

When you join a room that already has state, you receive everything at once.

MultiplayerService.state_snapshot_received.connect(func(snap):
    for e in snap.entities:
        spawn_dot(e.entityId, e.state))

4. Room state & deletion

# Host-only shared state:
MultiplayerService.patch_room_state({ "round": 2, "phase": "combat" })
MultiplayerService.room_state_changed.connect(func(_patch, state): set_round(state.round))

# Remove your entity:
MultiplayerService.delete_entity_state(my_id)
MultiplayerService.entity_state_deleted.connect(func(id): remove_dot(id))

Rules & limits

  • Only an entity's owner can update/delete it; only the host can patch room state. Violations arrive on state_update_rejected.
  • Defaults: 50 entities/room, 4 KB per entity, 16 KB room state, 10 updates/sec/client.
  • v1 has no prediction or interpolation — interpolate on the client for smoothness.

Full version: the Simple State Sync Demo in sdk/godot-gdscript/examples/state_sync/.