detect_player_leave: Reacting When Players Abandon the Island
Every island has a moment when the tide goes out and a player disappears — they quit, disconnect, or the session ends. The `player_left_device` (the Detect Player Leave device) fires an event the instant that happens, giving your Verse code a chance to clean up state, award consolation points, or dramatically seal the clifftop vault they were guarding. This article shows you exactly how to wire that event in Verse and build real game reactions around it.
detect_player_leave in ~90 seconds.Overview
The Detect Player Leave device (Verse type: player_left_device) raises a single listenable event — PlayerLeftEvent — whenever a player exits the session. Drop one into your level, reference it from a creative_device, and subscribe to that event in OnBegin. From that moment on, every departure triggers your handler.
When to reach for it:
- Seal a vault or close a gate when the player who was guarding it leaves.
- Award bonus loot to surviving players when an opponent disconnects.
- Log or persist a player's progress before they fully exit.
- Trigger a cinematic or ambient sound at the clifftop cove when the last player leaves a zone.
Because the event fires after the player has already left, you cannot interact with their character — but you still receive the agent reference for stat lookups, map cleanup, and team-logic decisions.
API Reference
(API surface could not be resolved for this device.)
Walkthrough
Scenario: A sun-drenched clifftop cove holds a glowing treasure vault. One player is assigned as the Vault Guardian. The moment that guardian leaves the island — rage-quit, disconnect, or session end — the vault door slams shut, a warning billboard flashes, and every remaining player hears the alarm. We use PlayerLeftEvent to detect the departure and IsReferenced on a companion Player Reference device to check whether the leaver was specifically the guardian.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Localisation helper — message params must be <localizes>
VaultMessage<localizes>(S : string) : message = "{S}"
clifftop_vault_manager := class(creative_device):
# A Player Reference device pre-configured to track the Vault Guardian
@editable
GuardianReference : player_reference_device = player_reference_device{}
# A Mutator Zone or Trigger that represents the vault door being "sealed"
@editable
VaultSealTrigger : trigger_device = trigger_device{}
# A Billboard device to flash the warning message
@editable
WarningBoard : billboard_device = billboard_device{}
# Called once when the island starts
OnBegin<override>()<suspends> : void =
# Subscribe: whenever any player leaves the session, call OnPlayerLeft
GetPlayspace().PlayerRemovedEvent().Subscribe(OnPlayerLeft)
# Handler — fires each time a player leaves the session
OnPlayerLeft(LeavingAgent : agent) : void =
# Check: was the leaver the designated Vault Guardian?
GuardianAgent := GuardianReference.GetAgent()
if (GuardianAgent = LeavingAgent):
# Guardian is gone — seal the clifftop vault immediately
VaultSealTrigger.Trigger()
# Flash the billboard with a localized warning
WarningBoard.SetText(VaultMessage("⚠ The Guardian has left — Vault Sealed!"))```
**Line-by-line breakdown:**
| Lines | What's happening |
|---|---|
| `@editable LeaveDetector` | Binds the placed Detect Player Leave device so Verse can subscribe to it. |
| `@editable GuardianReference` | Binds a Player Reference device that the designer has pointed at the Guardian player slot. |
| `@editable VaultSealTrigger` | A Trigger device whose "Triggered" output is wired to the vault door's close animation. |
| `@editable WarningBoard` | A Billboard device that displays text to all players. |
| `LeaveDetector.PlayerLeftEvent.Subscribe(OnPlayerLeft)` | Registers our handler — from this point every player departure calls `OnPlayerLeft`. |
| `OnPlayerLeft(LeavingAgent : agent)` | The handler receives the departing player as an `agent`. |
| `GuardianReference.IsReferenced[LeavingAgent]` | Uses the failable `<decides>` method inside an `if` — succeeds only if the leaver is the tracked guardian. |
| `VaultSealTrigger.Trigger()` | Fires the trigger, closing the vault door. |
| `WarningBoard.SetText(...)` | Updates the billboard with a localized `message` value. |
## Common patterns
### Pattern 1 — Count remaining players and end the game when the island empties
Use `PlayerLeftEvent` to decrement a counter; when it hits zero, trigger a game-over sequence at the dock.
```verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
dock_session_manager := class(creative_device):
@editable
LeaveDetector : player_left_device = player_left_device{}
# An End Game device placed at the sunny dock
@editable
GameEnder : end_game_device = end_game_device{}
# Mutable player count — updated as players leave
var ActivePlayerCount : int = 0
OnBegin<override>()<suspends> : void =
# Snapshot current player count at game start
AllPlayers := GetPlayspace().GetPlayers()
set ActivePlayerCount = AllPlayers.Length
LeaveDetector.PlayerLeftEvent.Subscribe(OnPlayerLeft)
OnPlayerLeft(LeavingAgent : agent) : void =
set ActivePlayerCount = ActivePlayerCount - 1
if (ActivePlayerCount <= 0):
# Last player left the cove — end the session
GameEnder.Activate(LeavingAgent)
Key point: GetPlayspace().GetPlayers() gives the count at start; we decrement on each PlayerLeftEvent. When the dock is empty, end_game_device.Activate wraps the session.
Pattern 2 — Persist a stat snapshot the moment a player leaves
Capture the player's score (via a linked player_counter_device) before they fully exit, so the leaderboard stays accurate.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
shore_stat_saver := class(creative_device):
@editable
LeaveDetector : player_left_device = player_left_device{}
# A Stat Tracker device that has been counting this player's fish caught
@editable
FishCounter : stat_tracker_device = stat_tracker_device{}
# A Billboard to display the last recorded score at the shore
@editable
ScoreBoard : billboard_device = billboard_device{}
ScoreLabel<localizes>(N : int) : message = "Last leaver caught {N} fish!"
OnBegin<override>()<suspends> : void =
LeaveDetector.PlayerLeftEvent.Subscribe(OnPlayerLeft)
OnPlayerLeft(LeavingAgent : agent) : void =
# Read the current tracked stat value before the player is gone
LastScore := FishCounter.GetStatValue()
ScoreBoard.SetText(ScoreLabel(LastScore))
Key point: stat_tracker_device.GetStatValue() returns an int — no conversion needed. We call it synchronously inside the handler before the session cleans up the player's data.
Pattern 3 — Check if the leaver was the tracked guardian using IsReferenced
A focused snippet showing IsReferenced as a guard clause — useful whenever you only care about one specific player leaving, not the whole lobby.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
cove_guardian_check := class(creative_device):
@editable
LeaveDetector : player_left_device = player_left_device{}
@editable
GuardianRef : player_reference_device = player_reference_device{}
# Cinematic sequencer to play the "guardian gone" cutscene at the cove
@editable
GuardianGoneCinematic : cinematic_sequence_device = cinematic_sequence_device{}
OnBegin<override>()<suspends> : void =
LeaveDetector.PlayerLeftEvent.Subscribe(OnPlayerLeft)
OnPlayerLeft(LeavingAgent : agent) : void =
# IsReferenced<decides> — only enters the if-block for the tracked player
if (GuardianRef.IsReferenced[LeavingAgent]):
GuardianGoneCinematic.Play()
Key point: IsReferenced is a <decides> method — call it inside if (...) with bracket syntax [LeavingAgent], not parentheses. It silently fails (no runtime error) for every other leaver.
Gotchas
1. The agent is already gone — don't try to move or damage them
By the time PlayerLeftEvent fires, the player's character has been removed from the world. Calling character-manipulation APIs (teleport, damage, etc.) on the LeavingAgent will silently fail or throw a runtime error. Use the agent only for identity checks (IsReferenced) or stat reads.
2. IsReferenced uses bracket syntax, not parentheses
IsReferenced is marked <decides>, meaning it can fail. Always call it inside an if expression using square brackets:
# CORRECT
if (MyRef.IsReferenced[LeavingAgent]):
...
# WRONG — won't compile
if (MyRef.IsReferenced(LeavingAgent)):
...
3. SetText requires a <localizes> message, not a raw string
Billboard's SetText takes a message type. Declare a helper function with <localizes> and pass that — you cannot pass a plain string literal directly:
# CORRECT
MyLabel<localizes>(S : string) : message = "{S}"
Board.SetText(MyLabel("Vault Sealed"))
# WRONG — compile error
Board.SetText("Vault Sealed")
4. PlayerLeftEvent fires for ALL players — filter when you need specifics
If your logic only applies to one player (the guardian, the host, a VIP), always gate your handler with IsReferenced or a stored agent comparison. Without a filter, every departure — including spectators and late-joiners — triggers your logic.
5. int ↔ float is never automatic
GetStatValue() returns int. If you need it as a float (e.g., for a timer calculation), cast explicitly: Float(GetStatValue()). Verse will not coerce types silently.
Build your own lesson with detect_player_leave
Generate a personalized, compile-checked lesson grounded in this exact reference.
Build a lesson →