Overview
There is no single magic device named state-transition-with-set. In UEFN, a state transition is a technique: you keep a set of placed devices as @editable fields, then when something happens (a player steps on a plate, a timer succeeds), you set every device into the configuration that represents the new game state — enabling some, disabling others, playing a cinematic, starting a countdown.
Picture a bright, cel-shaded morning cove. The dock is peaceful (state A). A player walks to the end of the pier and a teleporter fires — the island snaps into 'high tide alarm' (state B): a warning cinematic plays, a timer starts counting down, a damage volume that floods the low rocks switches on, and a score manager begins awarding survival points. That coordinated snap is the state transition, and every line below calls a real device method to make it happen.
Reach for this pattern whenever a single moment must change several things at once and you want it all in one readable place instead of scattered across device wiring.
API Reference
(API surface could not be resolved for this device.)
Walkthrough
Our scenario: a sunny cove with a dock teleporter at the end of the pier. When any player steps into it and emerges (TeleportedEvent), we transition the whole cove from calm to high-tide alarm.
The transition sets:
- the alarm cinematic to
Play - the survival timer to
Startfor that player - the flood damage volume to
Enable+SetDamage - the score manager to
Enableso survival points can flow
using { /UnrealEngine.com/Temporary/UI }
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
cove_state_manager := class(creative_device):
# The rift at the end of the pier that kicks off the alarm.
@editable DockTeleporter : teleporter_device = teleporter_device{}
# The warning cinematic that plays when high tide starts.
@editable AlarmCinematic : cinematic_sequence_device = cinematic_sequence_device{}
# Countdown the player must survive.
@editable SurvivalTimer : timer_device = timer_device{}
# Water that floods the low rocks during the alarm.
@editable FloodVolume : damage_volume_device = damage_volume_device{}
# Awards points while the alarm is active.
@editable SurvivalScore : score_manager_device = score_manager_device{}
OnBegin<override>()<suspends>:void =
# Start in the CALM state: flood off, score off.
FloodVolume.Disable()
SurvivalScore.Disable()
# When a player emerges from the dock rift, transition to ALARM.
DockTeleporter.TeleportedEvent.Subscribe(OnDockUsed)
# If they survive the timer, transition back to CALM.
SurvivalTimer.SuccessEvent.Subscribe(OnSurvived)
# Handler for a listenable(agent): the agent is delivered directly.
OnDockUsed(Agent : agent) : void =
EnterAlarmState(Agent)
EnterAlarmState(Agent : agent) : void =
# --- SET the island into the high-tide ALARM state ---
AlarmCinematic.Play() # rolling wave warning cutscene
SurvivalTimer.Start(Agent) # begin this player's countdown
FloodVolume.SetDamage(25) # each tick chews 25 while flooded
FloodVolume.Enable() # switch the flooding water ON
SurvivalScore.Enable(Agent) # allow survival points
# SuccessEvent hands a ?agent (optional) — unwrap before use.
OnSurvived(MaybeAgent : ?agent) : void =
# --- SET the island back to CALM ---
FloodVolume.Disable()
AlarmCinematic.Stop()
if (Agent := MaybeAgent?):
SurvivalScore.Activate(Agent) # pay out for surviving
Line by line:
- Each device the transition touches is an
@editablefield, so you drop the real placed device onto it in the Details panel. Without these fields, calling.Play()etc. fails with Unknown identifier. - In
OnBeginwe first set the initial state — flood and score disabled — so the cove opens peaceful. - We subscribe two transitions:
TeleportedEvent(calm → alarm) andSuccessEvent(alarm → calm). TeleportedEventis alistenable(agent), soOnDockUsedreceives theAgentdirectly, no unwrap needed.EnterAlarmStateis the transition: it calls five real methods in a row. That block IS the 'set' — every device is placed into its alarm configuration.SuccessEventis alistenable(?agent), soOnSurvivedgets a?agent; we unwrap withif (Agent := MaybeAgent?):before awarding points.
Common patterns
Reset the state with Reset and Clear
When a round ends you often want to wipe every stateful device back to zero. timer_device and score_manager_device both have Reset, and player_reference_device has Clear.
using { /UnrealEngine.com/Temporary/UI }
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
cove_round_reset := class(creative_device):
@editable ResetTeleporter : teleporter_device = teleporter_device{}
@editable RoundTimer : timer_device = timer_device{}
@editable RoundScore : score_manager_device = score_manager_device{}
@editable LeaderRef : player_reference_device = player_reference_device{}
OnBegin<override>()<suspends>:void =
ResetTeleporter.EnterEvent.Subscribe(OnReset)
OnReset(Agent : agent) : void =
# Snap all stateful devices back to their opening state.
RoundTimer.Reset()
RoundScore.Reset()
LeaderRef.Clear()
Spawn players into a fresh state
A player_spawner_device transition: when a player spawns, register them in a reference device and start their personal timer.
using { /UnrealEngine.com/Temporary/UI }
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
cove_spawn_setup := class(creative_device):
@editable Spawner : player_spawner_device = player_spawner_device{}
@editable RunTimer : timer_device = timer_device{}
@editable RunnerRef : player_reference_device = player_reference_device{}
OnBegin<override>()<suspends>:void =
Spawner.SpawnedEvent.Subscribe(OnSpawned)
OnSpawned(Agent : agent) : void =
RunnerRef.Register(Agent) # track this runner
RunTimer.Start(Agent) # begin their run
Toggle a cinematic state with PlayReverse
A clifftop drawbridge cinematic: entering the volume plays it forward (bridge down = passable state), leaving reverses it (bridge up).
using { /UnrealEngine.com/Temporary/UI }
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
cove_bridge_toggle := class(creative_device):
@editable BridgeZone : damage_volume_device = damage_volume_device{}
@editable BridgeSeq : cinematic_sequence_device = cinematic_sequence_device{}
OnBegin<override>()<suspends>:void =
BridgeZone.AgentEntersEvent.Subscribe(OnEnter)
BridgeZone.AgentExitsEvent.Subscribe(OnExit)
OnEnter(Agent : agent) : void =
BridgeSeq.Play() # lower the bridge
OnExit(Agent : agent) : void =
BridgeSeq.PlayReverse() # raise it again
Gotchas
listenable(agent)vslistenable(?agent).TeleportedEvent,EnterEvent,SpawnedEvent, andAgentEntersEventhand you a plainagent— use it directly. Buttimer_device'sSuccessEvent/FailureEventhand a?agent; you MUST unwrap withif (A := MaybeAgent?):before passing it to methods that need anagent.- Fields or nothing. You cannot write
teleporter_device{}.Activate(...)inline and expect it to hit a placed device. Only an@editablefield bound in the Details panel refers to the real device in the level. - Overloads need the right arg. Many methods have both a no-arg and an
(Agent:agent)form (score_manager_device.Enable,timer_device.Start,cinematic_sequence_device.Play). The agent overload is required when the device's Activating Team/Player is set to anything other than Everyone — pick the overload that matches your device settings or the call silently does nothing. SetDamageis clamped.damage_volume_device.SetDamageclamps to 1–500; passing 0 does not turn it off — callDisable()to stop damage.- Set the initial state explicitly. Devices keep their editor-configured state until you touch them. If your 'calm' state needs the flood off, call
Disable()inOnBegin— don't assume it starts disabled. intvsfloat.SetDamagetakes anint(25), while aDamage(Amount:float)override takes afloat(25.0). Verse will not auto-convert between them.