Quick answer: Add the scene to the spawner’s spawnable_scenes array. Spawn only on the server (authority=1); MultiplayerSpawner replicates from there.
A multiplayer co-op game uses MultiplayerSpawner to replicate enemies. Server sees them, clients don’t. The scene wasn’t registered with the spawner.
Register Spawnable Scenes
In editor, select MultiplayerSpawner node. Inspector → Spawnable Scenes → add res://enemy.tscn. Each replicated scene type must be listed.
Spawn on Server Only
if multiplayer.is_server():
var enemy = enemy_scene.instantiate()
$SpawnParent.add_child(enemy, true) # true = force_readable_name
The MultiplayerSpawner watches the spawn path; new children get replicated to all peers.
spawn_path Configuration
The spawner has a spawn_path property — the parent node where new children appear. Verify it matches where you add_child. Mismatch = spawner doesn’t see additions.
Custom Spawn Data
For per-spawn parameters (position, type), use custom spawn function:
multiplayer_spawner.spawn_function = _custom_spawn
func _custom_spawn(data) -> Node:
var e = enemy_scene.instantiate()
e.position = data
return e
# server:
multiplayer_spawner.spawn(Vector2(100, 200))
Clients call _custom_spawn with the same data, building identical instances.
Verifying
Host + 2 clients. Server spawns enemy — both clients see it appear. Despawn on server — both clients remove. No desync.
“MultiplayerSpawner is a server-authoritative replicator. Register scenes, spawn server-side, watch them propagate.”
For PVP games with cheaters in mind, never trust client spawn calls — only server side spawns. Spawner enforces this by design.