Overview
The vehicle_spawner_biplane_device is a specialized vehicle_spawner_device that spawns a Stormwing biplane — Fortnite's classic two-seat aircraft with a pilot machine gun and a passenger seat. It solves the problem of programmatic vehicle control: instead of letting the spawner sit there passively, Verse lets you enable/disable it, force a specific player into the pilot seat, destroy and respawn the plane on a timer, and react when players climb in or bail out.
Reach for this device when you're building an air-combat round, a racing checkpoint that hands the leader a plane, or a survival mode where the aircraft respawns after each crash. Because it inherits everything from vehicle_spawner_device, the same events and methods shown here apply to every other vehicle spawner (boats, tanks, UFOs, etc.) — learn it once, use it everywhere.
Key moving parts:
- Events like
SpawnedEvent,AgentEntersVehicleEvent, andDestroyedEventlet you react to the plane's lifecycle. - Methods like
Enable,Disable,AssignDriver,DestroyVehicle, andRespawnVehiclelet you drive that lifecycle from code.
API Reference
vehicle_spawner_biplane_device
Specialized
vehicle_spawner_devicethat allows a Stormwing biplane to be configured and spawned.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse). Inherited members are merged from vehicle_spawner_device.
vehicle_spawner_biplane_device<public> := class<concrete><final>(vehicle_spawner_device):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
AgentEntersVehicleEvent |
AgentEntersVehicleEvent<public>:listenable(agent) |
Signaled when an agent enters the vehicle. Sends the agent that entered the vehicle. |
AgentExitsVehicleEvent |
AgentExitsVehicleEvent<public>:listenable(agent) |
Signaled when an agent exits the vehicle. Sends the agent that exited the vehicle. |
SpawnedEvent |
SpawnedEvent<public>:listenable(fort_vehicle) |
Signaled when a vehicle is spawned or respawned by this device. Sends the fort_vehicle who was spawned. |
VehicleSpawnedEvent |
VehicleSpawnedEvent<public>:listenable(tuple()) |
Signaled when a vehicle is spawned or respawned by this device. Deprecated, use SpawnedEvent instead. |
VehicleDestroyedEvent |
VehicleDestroyedEvent<public>:listenable(tuple()) |
Signaled when a vehicle is destroyed. Deprecated, use DestroyedEvent instead. |
DestroyedEvent |
DestroyedEvent<public>:listenable(tuple()) |
Signaled when a vehicle is destroyed. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Enable |
Enable<public>():void |
Enables this device. |
Disable |
Disable<public>():void |
Disables this device. |
AssignDriver |
AssignDriver<public>(Agent:agent):void |
Sets agent as the vehicle's driver. |
DestroyVehicle |
DestroyVehicle<public>():void |
Destroys the vehicle if it exists. |
RespawnVehicle |
RespawnVehicle<public>():void |
Spawns a new vehicle. The previous vehicle will be destroyed before a new vehicle spawns. |
vehicle_spawner_device
Base class for various specialized vehicle spawners which allow specific vehicle types to be spawned and configured with specialized options.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
vehicle_spawner_device<public> := class<abstract><epic_internal>(creative_device_base):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
AgentEntersVehicleEvent |
AgentEntersVehicleEvent<public>:listenable(agent) |
Signaled when an agent enters the vehicle. Sends the agent that entered the vehicle. |
AgentExitsVehicleEvent |
AgentExitsVehicleEvent<public>:listenable(agent) |
Signaled when an agent exits the vehicle. Sends the agent that exited the vehicle. |
SpawnedEvent |
SpawnedEvent<public>:listenable(fort_vehicle) |
Signaled when a vehicle is spawned or respawned by this device. Sends the fort_vehicle who was spawned. |
VehicleSpawnedEvent |
VehicleSpawnedEvent<public>:listenable(tuple()) |
Signaled when a vehicle is spawned or respawned by this device. Deprecated, use SpawnedEvent instead. |
VehicleDestroyedEvent |
VehicleDestroyedEvent<public>:listenable(tuple()) |
Signaled when a vehicle is destroyed. Deprecated, use DestroyedEvent instead. |
DestroyedEvent |
DestroyedEvent<public>:listenable(tuple()) |
Signaled when a vehicle is destroyed. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Enable |
Enable<public>():void |
Enables this device. |
Disable |
Disable<public>():void |
Disables this device. |
AssignDriver |
AssignDriver<public>(Agent:agent):void |
Sets agent as the vehicle's driver. |
DestroyVehicle |
DestroyVehicle<public>():void |
Destroys the vehicle if it exists. |
RespawnVehicle |
RespawnVehicle<public>():void |
Spawns a new vehicle. The previous vehicle will be destroyed before a new vehicle spawns. |
Walkthrough
Let's build a "Sky Duel" scenario. When a player steps on a trigger, the biplane spawner is enabled and forces that player into the pilot seat. We track when anyone enters or exits, and when the plane is destroyed we automatically respawn it after a short delay so the action never stops.
using { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }
using { /Fortnite.com/Vehicles }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
sky_duel := class(creative_device):
# Drag your Biplane Spawner into this slot in the Details panel.
@editable
BiplaneSpawner : vehicle_spawner_biplane_device = vehicle_spawner_biplane_device{}
# A trigger the player steps on to launch.
@editable
LaunchTrigger : trigger_device = trigger_device{}
# Localized message helper (message params need localized text, not raw strings).
Announce<localizes>(S:string):message = "{S}"
OnBegin<override>()<suspends>:void =
# Start with the spawner off so no plane exists until a player launches.
BiplaneSpawner.Disable()
# React to the biplane's whole lifecycle.
BiplaneSpawner.SpawnedEvent.Subscribe(OnPlaneSpawned)
BiplaneSpawner.AgentEntersVehicleEvent.Subscribe(OnAgentEnters)
BiplaneSpawner.AgentExitsVehicleEvent.Subscribe(OnAgentExits)
BiplaneSpawner.DestroyedEvent.Subscribe(OnPlaneDestroyed)
# When a player steps on the trigger, launch them.
LaunchTrigger.TriggeredEvent.Subscribe(OnLaunchPressed)
# Trigger handler: enable the spawner, spawn a fresh plane, seat the player.
OnLaunchPressed(Agent : ?agent):void =
if (Pilot := Agent?):
BiplaneSpawner.Enable()
# RespawnVehicle guarantees a plane exists (destroys the old one first).
BiplaneSpawner.RespawnVehicle()
# Put this exact player in the pilot seat.
BiplaneSpawner.AssignDriver(Pilot)
Print("Launch requested by a pilot.")
# SpawnedEvent hands us the fort_vehicle that appeared.
OnPlaneSpawned(Vehicle : fort_vehicle):void =
Print("A Stormwing has spawned and is ready to fly.")
# AgentEntersVehicleEvent / AgentExitsVehicleEvent hand us an agent.
OnAgentEnters(Agent : agent):void =
Print("A pilot climbed aboard the Stormwing.")
OnAgentExits(Agent : agent):void =
Print("Someone bailed out of the Stormwing.")
# When the plane is destroyed, respawn it after 3 seconds.
OnPlaneDestroyed():void =
spawn { RespawnAfterDelay() }
RespawnAfterDelay()<suspends>:void =
Sleep(3.0)
BiplaneSpawner.RespawnVehicle()
Print("A new Stormwing has been deployed.")```
**Line by line:**
- The two `@editable` fields (`BiplaneSpawner`, `LaunchTrigger`) are how Verse reaches the devices you placed in the level — you bind them in the Details panel. Without these fields you cannot call the device's methods.
- `BiplaneSpawner.Disable()` in `OnBegin` keeps the sky empty until a player opts in.
- Each `Subscribe(...)` wires one of the device's real events to a method on this class. Note that `SpawnedEvent` passes a `fort_vehicle`, the enter/exit events pass an `agent`, and `DestroyedEvent` passes nothing (`tuple()`), so `OnPlaneDestroyed` takes no parameter.
- `OnLaunchPressed(Agent : ?agent)` — the trigger's `TriggeredEvent` is a `listenable(?agent)`, so we unwrap with `if (Pilot := Agent?)` before using the player.
- `Enable()` + `RespawnVehicle()` + `AssignDriver(Pilot)` is the core launch sequence: turn the device on, force a fresh plane, and seat the player who pressed the trigger.
- `OnPlaneDestroyed` uses `spawn { ... }` to start an independent async task (`RespawnAfterDelay`) so the event handler returns immediately while the 3-second `Sleep` runs in the background.
## Common patterns
### Toggle the spawner with Enable / Disable
A "hangar" you open and close. While disabled the plane can't be respawned, keeping the airspace clear during a ground phase.
```verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
hangar_control := class(creative_device):
@editable
BiplaneSpawner : vehicle_spawner_biplane_device = vehicle_spawner_biplane_device{}
@editable
OpenButton : button_device = button_device{}
@editable
CloseButton : button_device = button_device{}
OnBegin<override>()<suspends>:void =
OpenButton.InteractedWithEvent.Subscribe(OnOpen)
CloseButton.InteractedWithEvent.Subscribe(OnClose)
OnOpen(Agent : agent):void =
BiplaneSpawner.Enable()
BiplaneSpawner.RespawnVehicle()
Print("Hangar open - Stormwing deployed.")
OnClose(Agent : agent):void =
BiplaneSpawner.DestroyVehicle()
BiplaneSpawner.Disable()
Print("Hangar closed - airspace cleared.")
React to spawn vs destroy to keep score
Count how many Stormwings get shot down during a round using SpawnedEvent and DestroyedEvent.
using { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
plane_scorekeeper := class(creative_device):
@editable
BiplaneSpawner : vehicle_spawner_biplane_device = vehicle_spawner_biplane_device{}
var PlanesLost : int = 0
OnBegin<override>()<suspends>:void =
BiplaneSpawner.SpawnedEvent.Subscribe(OnSpawned)
BiplaneSpawner.DestroyedEvent.Subscribe(OnDestroyed)
BiplaneSpawner.Enable()
BiplaneSpawner.RespawnVehicle()
OnSpawned(Vehicle : fort_vehicle):void =
Print("Fresh Stormwing in the air.")
OnDestroyed():void =
set PlanesLost += 1
Print("Planes lost this round: {PlanesLost}")
Force a specific player into the cockpit on entry
Use AgentEntersVehicleEvent plus AssignDriver to make whoever touches the plane the designated pilot — handy for a "first come, first fly" rule.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
auto_pilot := class(creative_device):
@editable
BiplaneSpawner : vehicle_spawner_biplane_device = vehicle_spawner_biplane_device{}
OnBegin<override>()<suspends>:void =
BiplaneSpawner.AgentEntersVehicleEvent.Subscribe(OnEntered)
BiplaneSpawner.Enable()
BiplaneSpawner.RespawnVehicle()
OnEntered(Agent : agent):void =
# Promote the entering agent to driver so they take the pilot seat.
BiplaneSpawner.AssignDriver(Agent)
Print("Assigned the entering agent as pilot.")
Gotchas
- You must declare the spawner as an
@editablefield inside yourcreative_deviceclass and bind it in the Details panel. Callingvehicle_spawner_biplane_device{}.Enable()on a bare value does nothing useful — it must reference a placed device. - Event payloads differ.
SpawnedEventgives afort_vehicle,AgentEntersVehicleEvent/AgentExitsVehicleEventgive anagent, andDestroyedEvent/VehicleDestroyedEvent/VehicleSpawnedEventgivetuple()(no parameter). Match your handler's signature accordingly or the subscribe won't compile. - Prefer
SpawnedEventandDestroyedEvent—VehicleSpawnedEventandVehicleDestroyedEventare deprecated. They still work but you should not write new code against them. RespawnVehicledestroys the old plane first. If a player is mid-flight when you call it, they'll be dropped. Use it deliberately, not on a tight loop.AssignDriverneeds anagent, not a?agent. When the source is a trigger or button passing?agent, unwrap it first withif (P := Agent?):before callingAssignDriver(P).Disabledoes not destroy an existing plane. If you want a clean airspace, callDestroyVehicle()beforeDisable(), as shown in the hangar pattern.message-typed parameters need localized text. If a device method or UI element wants amessage, build it with a<localizes>helper likeAnnounce<localizes>(S:string):message = "{S}"— there is noStringToMessage.