Overview
The skydive_volume_device defines a zone that throws any agent inside it into a skydive state — the same controllable free-fall you get when leaving the Battle Bus. Designers configure push force and launch speed in the Details panel; rotating and overlapping several volumes lets you build pneumatic tubes that fling players in chosen directions, or vertical shafts that boost them onto rooftops they couldn't otherwise reach.
Reach for it when you want movement, not damage: a launch pad at the bottom of a tower, a fall chute between floors, a 'wind tunnel' traversal puzzle, or a vent that yeets escaping players back into a boss arena.
In Verse you don't usually set the push force (that's the device options) — instead you react to who is inside. The device extends effect_volume_device and gives you four events (AgentEntersEvent, AgentExitsEvent, ZoneOccupiedEvent, ZoneEmptiedEvent) plus methods to query occupants (GetAgentsInVolume, IsInVolume), toggle the device (Enable/Disable), and even trap players inside (EnableVolumeLocking/DisableVolumeLocking).
API Reference
skydive_volume_device
Used to create a zone where players are put into a skydive state. Can customize the amount of force used to push the player, and how fast players are launched into the air. The direction of the push is in relation to the device, so you can rotate and overlap several devices, then use variable speeds to create pneumatic tubes that propel players in different directions. You can even create unique t
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse). Inherited members are merged from effect_volume_device.
skydive_volume_device<public> := class<concrete><final>(effect_volume_device):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
AgentEntersEvent |
AgentEntersEvent<public>:listenable(agent) |
Signaled when an agent enters the volume. Sends the agent that entered the volume. |
AgentExitsEvent |
AgentExitsEvent<public>:listenable(agent) |
Signaled when an agent exits the volume. Sends the agent that exited the volume. |
ZoneOccupiedEvent |
ZoneOccupiedEvent<public>:listenable(agent) |
Signaled when the zone changes from empty to occupied. Sends the agent that entered the volume. |
ZoneEmptiedEvent |
ZoneEmptiedEvent<public>:listenable(agent) |
Signaled when the zone changes from occupied to empty. Sends the agent that last left the volume. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
EnableVolumeLocking |
EnableVolumeLocking<public>():void |
Enables volume locking which prevents users from leaving the volume once they've entered. |
DisableVolumeLocking |
DisableVolumeLocking<public>():void |
Disables volume locking which prevents users from leaving the volume once they've entered. |
IsInVolume |
IsInVolume<public>(Agent:agent)<transacts><decides>:void |
Is true when Agent is in the volume. |
GetAgentsInVolume |
GetAgentsInVolume<public>()<reads>:[]agent |
Returns an array of agents that are currently occupying the volume. |
Enable |
Enable<public>():void |
Enables this device. |
Disable |
Disable<public>():void |
Disables this device. |
volume_device
Used to track when agents enter and exit a volume.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
volume_device<public> := class<concrete><final>(creative_device_base):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
AgentEntersEvent |
AgentEntersEvent<public>:listenable(agent) |
Signaled when an agent enters the device volume. |
AgentExitsEvent |
AgentExitsEvent<public>:listenable(agent) |
Signaled when an agent exits the device volume. |
PropEnterEvent |
PropEnterEvent<public>:listenable(creative_prop) |
Signaled when an creative_prop entered the device volume. |
PropExitEvent |
PropExitEvent<public>:listenable(creative_prop) |
Signaled when an creative_prop exited the device volume. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
GetAgentsInVolume |
GetAgentsInVolume<public>()<reads>:[]agent |
Returns an array of agents that are currently occupying the volume. |
IsInVolume |
IsInVolume<public>(Agent:agent)<transacts><decides>:void |
Succeeds when Agent is in the volume. |
Walkthrough
Let's build a launch tower. A skydive volume at the base flings players upward. We want to:
- Light up an alarm / start music when the FIRST player enters (the zone goes from empty to occupied).
- Grant a temporary effect or feedback each time ANY player enters.
- Show how many players are currently riding the tube.
- Reset things when the LAST player leaves.
We subscribe to the device's real events in OnBegin and call its real methods inside the handlers.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
launch_tower := class(creative_device):
# The skydive volume placed at the base of the tower.
@editable
SkydiveTube : skydive_volume_device = skydive_volume_device{}
# An audio device we turn on while at least one player is riding.
@editable
AmbientAudio : audio_player_device = audio_player_device{}
OnBegin<override>()<suspends>:void =
# React to the very first player entering an empty zone.
SkydiveTube.ZoneOccupiedEvent.Subscribe(OnZoneOccupied)
# React to the last player leaving.
SkydiveTube.ZoneEmptiedEvent.Subscribe(OnZoneEmptied)
# React to EACH individual entry.
SkydiveTube.AgentEntersEvent.Subscribe(OnAgentEnters)
# React to EACH individual exit.
SkydiveTube.AgentExitsEvent.Subscribe(OnAgentExits)
# ZoneOccupiedEvent hands us the agent that filled the empty zone.
OnZoneOccupied(Agent : agent) : void =
AmbientAudio.Play()
Print("Launch tube active!")
# ZoneEmptiedEvent hands us the agent that last left.
OnZoneEmptied(Agent : agent) : void =
AmbientAudio.Stop()
Print("Launch tube idle.")
# Fires for every agent that enters, even if the zone was already busy.
OnAgentEnters(Agent : agent) : void =
# GetAgentsInVolume returns everyone currently riding.
Riders := SkydiveTube.GetAgentsInVolume()
Print("A player entered. Riders now: {Riders.Length}")
OnAgentExits(Agent : agent) : void =
# IsInVolume is a <decides> query — use it inside an if.
if (SkydiveTube.IsInVolume[Agent]):
Print("Exit fired but agent still tracked inside.")
else:
Print("A player left the launch tube.")
Line by line:
@editable SkydiveTube : skydive_volume_device = skydive_volume_device{}— the field you drag your placed device onto in the editor. You MUST declare it as an editable field; callingskydive_volume_device.Method()directly fails with Unknown identifier.- In
OnBeginweSubscribefour handlers. Each event is alistenable(agent), so every handler takes a single(Agent : agent)parameter. ZoneOccupiedEventonly fires on the transition from empty→occupied, so it's the right place to start music.ZoneEmptiedEventfires occupied→empty, so it stops music. This is much cleaner than counting entries yourself.AgentEntersEvent/AgentExitsEventfire for every player, so we use them for per-player bookkeeping.GetAgentsInVolume()gives the live occupant list —.Lengthis the rider count.IsInVolume[Agent]is a<decides>function: it doesn't return a bool, it succeeds or fails, so it must be called inside anifwith square brackets.
Common patterns
Pattern 1 — Trap players with volume locking (boss-arena vent)
Lock the volume so any player who steps into the vent cannot leave until you unlock it — great for forcing a respawn loop or a 'sky cage' mini-game.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
sky_cage := class(creative_device):
@editable
Vent : skydive_volume_device = skydive_volume_device{}
OnBegin<override>()<suspends>:void =
# Once someone enters, lock the volume so they're stuck skydiving.
Vent.AgentEntersEvent.Subscribe(OnEnter)
OnEnter(Agent : agent) : void =
Vent.EnableVolumeLocking()
# ...later, after a timer or objective, free them:
# Vent.DisableVolumeLocking()
Pattern 2 — Enable/Disable the tube as a gated mechanic
Keep the launch tube dormant until a switch is flipped, then turn it on.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
gated_tube := class(creative_device):
@editable
Tube : skydive_volume_device = skydive_volume_device{}
@editable
PowerSwitch : button_device = button_device{}
OnBegin<override>()<suspends>:void =
# Start with the tube off.
Tube.Disable()
PowerSwitch.InteractedWithEvent.Subscribe(OnSwitch)
OnSwitch(Agent : agent) : void =
# Flip the tube on when the switch is pressed.
Tube.Enable()
Pattern 3 — Per-agent rewards using GetAgentsInVolume on a timer
Use ZoneEmptiedEvent plus the occupant list to detect 'everyone has launched' and report the final rider.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
launch_counter := class(creative_device):
@editable
Tube : skydive_volume_device = skydive_volume_device{}
OnBegin<override>()<suspends>:void =
Tube.ZoneEmptiedEvent.Subscribe(OnEmptied)
OnEmptied(Agent : agent) : void =
# Agent here is the LAST player who left.
# Confirm the volume is truly empty.
Remaining := Tube.GetAgentsInVolume()
if (Remaining.Length = 0):
Print("Everyone has launched — tube clear.")
Gotchas
- You must use an
@editablefield. A bareSkydiveTube.Enable()whereSkydiveTubeisn't a declared field gives Unknown identifier. Declare it at class scope and drag the placed device onto it in the editor. IsInVolumeis<decides>, not a bool. Call it asif (Tube.IsInVolume[Agent]):with square brackets. Writingif (Tube.IsInVolume(Agent)):or treating it likeTube.IsInVolume(Agent) = truewon't compile.ZoneOccupiedEvent≠AgentEntersEvent.AgentEntersEventfires for every player;ZoneOccupiedEventonly on the empty→occupied transition. Don't start your music onAgentEntersEventor it'll restart every time a second player jumps in.- Volume locking persists.
EnableVolumeLocking()keeps players inside until you explicitly callDisableVolumeLocking(). If you forget to unlock, players are stuck skydiving forever — always pair them with a clear release condition. Disable()stops the skydive effect. A disabled skydive volume no longer launches players, so re-Enable()it before expecting entry events to do anything useful.- The handler param is
agent, notplayer. Events deliver anagent. If you need player-specific APIs, get the agent's player from it where required — but the entry/exit and zone events all type their payload asagent. - No
using { /Verse.org/Simulation }for events?creative_deviceandSubscriberely on the device imports; keep yourusinglines (the compile gate adds the device modules) soSubscribeandcreative_deviceresolve.