Overview
The player_spawner_device is UEFN's answer to "where does this player come back to life?" Placed like any Creative device, it acts as a physical spawn point on your island. From Verse you can call SpawnPlayer to force a specific player to respawn at that pad, and subscribe to SpawnedEvent to know the moment someone materialises there.
Use it when:
- Players should respawn at a checkpoint they last reached (a dock, a cove entrance, a clifftop flag).
- You want to split teams across different spawn pads at round start.
- A game event (a wave clear, a boss kill) should relocate where the next respawn happens.
- You need to react to a spawn — granting a weapon, playing a cinematic, starting a timer.
The companion free function RespawnAtPlayerSpawner(Player, SpawnerGroup) lets you pass an array of spawners and the runtime picks the most appropriate one — perfect for dynamic checkpoint systems.
API Reference
(API surface could not be resolved for this device.)
Walkthrough
Scenario — Sunny Cove Checkpoint Race
Your island is a cel-shaded coastal race: three docks jut into a bright turquoise bay. When a player steps on a dock trigger, that dock becomes their active respawn point. If they fall into the water (a damage volume beneath the cliffs) they respawn right back at their last dock. A cinematic sequence plays a short "splash" cutscene before they reappear.
Place in UEFN:
- Three
trigger_devices on the dock planks (DockTrigger1/2/3) - Three
player_spawner_devices behind each dock (DockSpawner1/2/3) - One
damage_volume_devicecovering the deep water - One
cinematic_sequence_devicefor the splash cutscene
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Fortnite.com/Characters }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Maps each player to the index of their current checkpoint spawner.
# 0 = start beach, 1 = Dock 1, 2 = Dock 2, 3 = Dock 3
checkpoint_race_manager := class(creative_device):
# --- Dock trigger pads (place on the dock planks) ---
@editable
DockTrigger1 : trigger_device = trigger_device{}
@editable
DockTrigger2 : trigger_device = trigger_device{}
@editable
DockTrigger3 : trigger_device = trigger_device{}
# --- Spawn pads behind each dock ---
@editable
DockSpawner1 : player_spawner_device = player_spawner_device{}
@editable
DockSpawner2 : player_spawner_device = player_spawner_device{}
@editable
DockSpawner3 : player_spawner_device = player_spawner_device{}
# --- Water damage volume under the cliffs ---
@editable
WaterVolume : damage_volume_device = damage_volume_device{}
# --- Splash cinematic before respawn ---
@editable
SplashCinematic : cinematic_sequence_device = cinematic_sequence_device{}
# Tracks each player's active checkpoint index (1, 2, or 3).
# We use a simple weak_map so it persists across the session.
var PlayerCheckpoint : weak_map(player, int) = map{}
OnBegin<override>()<suspends> : void =
# Subscribe to each dock trigger
DockTrigger1.TriggeredEvent.Subscribe(OnDock1Reached)
DockTrigger2.TriggeredEvent.Subscribe(OnDock2Reached)
DockTrigger3.TriggeredEvent.Subscribe(OnDock3Reached)
# Subscribe to the water volume — falling in triggers respawn
WaterVolume.AgentEntersEvent.Subscribe(OnPlayerHitsWater)
# Subscribe to each spawner so we know when a player materialises
DockSpawner1.SpawnedEvent.Subscribe(OnPlayerSpawned)
DockSpawner2.SpawnedEvent.Subscribe(OnPlayerSpawned)
DockSpawner3.SpawnedEvent.Subscribe(OnPlayerSpawned)
# --- Dock checkpoint handlers ---
OnDock1Reached(Agent : ?agent) : void =
if (P := player[Agent?]):
SetCheckpoint(P, 1)
OnDock2Reached(Agent : ?agent) : void =
if (P := player[Agent?]):
SetCheckpoint(P, 2)
OnDock3Reached(Agent : ?agent) : void =
if (P := player[Agent?]):
SetCheckpoint(P, 3)
# Record the player's latest checkpoint.
SetCheckpoint(P : player, Index : int) : void =
set PlayerCheckpoint[P] = Index
# --- Water volume: play splash cinematic then respawn at checkpoint ---
OnPlayerHitsWater(Agent : agent) : void =
spawn { HandleWaterRespawn(Agent) }
HandleWaterRespawn(Agent : agent)<suspends> : void =
# Play the splash cutscene for this player
SplashCinematic.Play(Agent)
# Wait a beat for the cinematic to breathe
Sleep(1.5)
if (P := player[Agent]):
# Look up which dock they last reached
if (CheckpointIndex := PlayerCheckpoint[P]):
RespawnAtCheckpoint(P, CheckpointIndex)
else:
# No checkpoint yet — use Dock 1 as the default
DockSpawner1.SpawnPlayer(P)
RespawnAtCheckpoint(P : player, Index : int) : void =
if (Index = 1):
DockSpawner1.SpawnPlayer(P)
else if (Index = 2):
DockSpawner2.SpawnPlayer(P)
else if (Index = 3):
DockSpawner3.SpawnPlayer(P)
else:
DockSpawner1.SpawnPlayer(P)
# --- SpawnedEvent: runs every time a player materialises at any dock spawner ---
OnPlayerSpawned(Agent : ?agent) : void =
if (P := player[Agent?]):
# Could grant a shield potion, play a sound, etc.
# Here we just log for debugging.
Print("Player respawned at a dock checkpoint.")```
### Line-by-line highlights
| Lines | What's happening |
|---|---|
| `@editable DockSpawner1..3` | Three `player_spawner_device` fields wired in the UEFN Details panel — required to call their methods. |
| `DockTrigger1.TriggeredEvent.Subscribe(OnDock1Reached)` | Dock plank trigger fires when a player steps on it; we record their checkpoint. |
| `WaterVolume.AgentEntersEvent.Subscribe(OnPlayerHitsWater)` | The damage volume under the cliffs fires when someone falls in. |
| `DockSpawner1.SpawnedEvent.Subscribe(OnPlayerSpawned)` | We listen to every spawner so we can react the instant a player appears. |
| `spawn { HandleWaterRespawn(Agent) }` | We need `Sleep` inside the handler, so we launch a concurrent task. |
| `SplashCinematic.Play(Agent)` | Plays the splash cutscene for the specific player who fell. |
| `Sleep(1.5)` | Waits for the cinematic beat before the respawn call. |
| `DockSpawner2.SpawnPlayer(P)` | The core call — forces `P` to respawn at this exact pad. |
## Common patterns
### Pattern 1 — Team split at round start
Force every player onto their team's spawn pad the moment the round begins. Uses `SpawnPlayer` on every connected player.
```verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Fortnite.com/Teams }
using { /Fortnite.com/Characters }
team_split_spawner := class(creative_device):
@editable
RoundStartTrigger : trigger_device = trigger_device{}
@editable
Team1Spawner : player_spawner_device = player_spawner_device{}
@editable
Team2Spawner : player_spawner_device = player_spawner_device{}
OnBegin<override>()<suspends> : void =
RoundStartTrigger.TriggeredEvent.Subscribe(OnRoundStart)
OnRoundStart(Agent : agent) : void =
spawn { SplitTeams() }
SplitTeams()<suspends> : void =
# Brief delay so the round-start UI can clear
Sleep(0.5)
# GetPlayspace().GetPlayers() returns all current players
AllPlayers := GetPlayspace().GetPlayers()
for (P : AllPlayers):
if (FortChar := P.GetFortCharacter[]):
# Use team index to decide which spawner to use
if (TeamCollection := GetPlayspace().GetTeamCollection[]):
if (TeamIndex := TeamCollection.GetTeam[P]):
if (TeamIndex.GetTeamIndex[] = 0):
Team1Spawner.SpawnPlayer(P)
else:
Team2Spawner.SpawnPlayer(P)
Pattern 2 — SpawnedEvent drives a welcome gift
Every time a player spawns at the clifftop pad, grant them a score bonus. Uses SpawnedEvent and score_manager_device.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
clifftop_spawn_reward := class(creative_device):
# The spawn pad at the top of the cliff
@editable
ClifftopSpawner : player_spawner_device = player_spawner_device{}
# Score manager that awards bonus points
@editable
BonusScorer : score_manager_device = score_manager_device{}
OnBegin<override>()<suspends> : void =
# Subscribe to SpawnedEvent — fires each time someone appears at this pad
ClifftopSpawner.SpawnedEvent.Subscribe(OnClifftopSpawn)
OnClifftopSpawn(Agent : agent) : void =
# Award the bonus to whoever just spawned here
BonusScorer.Activate(Agent)
Pattern 3 — RespawnAtPlayerSpawner with a group array
Pick the best available spawner from a pool — useful when some pads may be disabled mid-game (e.g., a cove pad that floods).
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Fortnite.com/Characters }
pool_respawn_manager := class(creative_device):
@editable
WaterVolume : damage_volume_device = damage_volume_device{}
# All available shore spawners — runtime picks the best valid one
@editable
ShoreSpawner1 : player_spawner_device = player_spawner_device{}
@editable
ShoreSpawner2 : player_spawner_device = player_spawner_device{}
@editable
ShoreSpawner3 : player_spawner_device = player_spawner_device{}
OnBegin<override>()<suspends> : void =
WaterVolume.AgentEntersEvent.Subscribe(OnFallIntoWater)
OnFallIntoWater(Agent : agent) : void =
spawn { DoPoolRespawn(Agent) }
DoPoolRespawn(Agent : agent)<suspends> : void =
Sleep(0.2)
if (P := player[Agent]):
# Pass the full pool — runtime selects the most appropriate valid spawner.
# If none are valid, the player skydives in.
RespawnAtPlayerSpawner(P, array{ShoreSpawner1, ShoreSpawner2, ShoreSpawner3})
Gotchas
1. You MUST declare spawners as @editable fields
Calling player_spawner_device{}.SpawnPlayer(P) on a default-constructed device does nothing — it has no position in the world. Always wire your placed devices through @editable fields in the Details panel.
2. SpawnPlayer on an alive player respects ShouldRespawnAlivePlayers
If the device's Should Respawn Alive Players setting is false (the default), calling SpawnPlayer on a player who is still alive is a no-op. Enable that setting in the device's Details panel if you need to teleport-via-respawn living players.
3. Event handlers can't Sleep — use spawn {}
SpawnedEvent and AgentEntersEvent handlers are synchronous callbacks. If you need to wait (e.g., for a cinematic) before calling SpawnPlayer, launch a concurrent task with spawn { MyCoroutine(Agent) } and put the Sleep there.
4. SpawnedEvent fires for ALL spawns at that pad
This includes the very first spawn at game start, not just respawns. Guard with a flag or round-state check if you only want to react to mid-game respawns.
5. RespawnAtPlayerSpawner with an empty array skydives the player
If every spawner in your group array is disabled or invalid, the player falls from the sky. Always keep at least one spawner enabled, or handle the skydive case intentionally.
6. player_spawner_device is not a teleporter
SpawnPlayer triggers a full respawn flow (respawn timer, shield reset, etc.). If you want instant position change without the respawn sequence, use a teleporter_device instead.