Overview
The item_spawner_device places a configurable item into the world that players can pick up. Out of the box you can configure it in the UEFN editor (item list, respawn delay, enabled state), but Verse lets you go further:
- Spawn on demand — call
SpawnItem()from any game event instead of relying on the editor timer. - Cycle items — call
CycleToNextItem()to advance through the device's configured item list, so one spawner can hand out different loot each round. - Control the respawn loop — toggle
SetEnableRespawnTimer()and tuneSetTimeBetweenSpawns()at runtime to make loot scarce late-game or abundant at the start. - React to pickup — subscribe to
ItemPickedUpEventto trigger score, cinematics, or the next wave of enemies the moment a player grabs the item. - Enable / Disable — gate the spawner entirely so it only becomes active when a puzzle is solved or a timer expires.
When to reach for it: Any time you need a physical item to appear in the world at a specific moment — weapon caches, collectibles, puzzle keys, health drops, or timed power-ups.
API Reference
item_spawner_device
Used to configuration and spawn items that players can pick up and use.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse). Inherited members are merged from base_item_spawner_device.
item_spawner_device<public> := class<concrete><final>(base_item_spawner_device):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
ItemPickedUpEvent |
ItemPickedUpEvent<public>:listenable(agent) |
Signaled when an agent picks up the spawned item. Sends the agent that picked up the item. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
CycleToNextItem |
CycleToNextItem<public>():void |
Cycles device to next configured item. |
SpawnItem |
SpawnItem<public>():void |
Spawns the current item. |
SetEnableRespawnTimer |
SetEnableRespawnTimer<public>((local:)Respawn:logic):void |
Sets device Respawn Item on Timer option (see SetTimeBetweenSpawns) |
GetEnableRespawnTimer |
GetEnableRespawnTimer<public>()<transacts>:logic |
Returns device Respawn Item on Timer option (see SetTimeBetweenSpawns) |
SetTimeBetweenSpawns |
SetTimeBetweenSpawns<public>(Time:float):void |
Sets the Time Between Spawns (in seconds) after an item is collected before the next is spawned, if this device has Respawn Item on Timer enabled (see SetEnableRespawnTimer) |
GetTimeBetweenSpawns |
GetTimeBetweenSpawns<public>()<transacts>:float |
Returns the Time Between Spawns (in seconds) after an item is collected before the next is spawned, if this device has Respawn Item on Timer enabled (see SetEnableRespawnTimer) |
Enable |
Enable<public>():void |
Enables this device. |
Disable |
Disable<public>():void |
Disables this device. |
vector3
3-dimensional vector with
floatcomponents.
Full public surface, resolved verbatim from the live Epic digest (Verse.digest.verse).
vector3<native><public> := struct<concrete><computes><persistable><uht_comparable>:
trigger_device
Used to relay events to other linked devices.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse). Inherited members are merged from trigger_base_device.
trigger_device<public> := class<concrete><final>(trigger_base_device):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
TriggeredEvent |
TriggeredEvent<public>:listenable(?agent) |
Signaled when an agent triggers this device. Sends the agent that used this device. Returns false if no agent triggered the action (ex: it was triggered through code). |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Trigger |
Trigger<public>(Agent:agent):void |
Triggers this device with Agent being passed as the agent that triggered the action. Use an agent reference when this device is setup to require one (for instance, you want to trigger the device only with a particular agent. |
Trigger |
Trigger<public>():void |
Triggers this device, causing it to activate its TriggeredEvent event. |
Enable |
Enable<public>():void |
Enables this device. |
Disable |
Disable<public>():void |
Disables this device. |
SetMaxTriggerCount |
SetMaxTriggerCount<public>(MaxCount:int):void |
Sets the maximum amount of times this device can trigger. * 0 can be used to indicate no limit on trigger count. * MaxCount is clamped between [0,20]. |
GetMaxTriggerCount |
GetMaxTriggerCount<public>()<transacts>:int |
Gets the maximum amount of times this device can trigger. * 0 indicates no limit on trigger count. |
GetTriggerCountRemaining |
GetTriggerCountRemaining<public>()<transacts>:int |
Returns the number of times that this device can still be triggered before hitting GetMaxTriggerCount. Returns 0 if GetMaxTriggerCount is unlimited. |
SetResetDelay |
SetResetDelay<public>(Time:float):void |
Sets the time (in seconds) after triggering, before the device can be triggered again (if MaxTrigger count allows). |
GetResetDelay |
GetResetDelay<public>()<transacts>:float |
Gets the time (in seconds) before the device can be triggered again (if MaxTrigger count allows). |
SetTransmitDelay |
SetTransmitDelay<public>(Time:float):void |
Sets the time (in seconds) which must pass after triggering, before this device informs other external devices that it has been triggered. |
GetTransmitDelay |
GetTransmitDelay<public>()<transacts>:float |
Gets the time (in seconds) which must pass after triggering, before this device informs other external devices that it has been triggered. |
Walkthrough
Scenario — The Sunken Treasure Dock
Your 2D cel-shaded pirate cove has a rickety dock jutting into a turquoise lagoon. A buried chest prop sits at the end. When a player steps on a pressure-plate trigger at the dock entrance, a legendary trident spawns on the chest. The moment someone picks it up, the spawner disables itself (no second trident!) and a cinematic sequence plays — the lagoon shakes and a kraken arm rises from the water.
After the cinematic the spawner re-enables with a longer respawn delay (60 s) so the trident can return for the next player, but this time it cycles to the next item in the list (a healing fish) to keep things fresh.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
# Place this device in UEFN and wire up the four @editable fields.
dock_treasure_manager := class(creative_device):
# The item spawner sitting on the chest prop at the end of the dock.
@editable TridentSpawner : item_spawner_device = item_spawner_device{}
# A trigger_device (pressure plate) at the dock entrance.
@editable DockTrigger : trigger_device = trigger_device{}
# A cinematic_sequence_device — kraken arm rising from the lagoon.
@editable KrakenCinematic : cinematic_sequence_device = cinematic_sequence_device{}
# -------------------------------------------------------
# Lifecycle
# -------------------------------------------------------
OnBegin<override>()<suspends> : void =
# The trident spawner starts disabled — nothing on the chest yet.
TridentSpawner.Disable()
# Wire up the pressure plate: when a player steps on it, spawn the trident.
DockTrigger.TriggeredEvent.Subscribe(OnDockEntered)
# Wire up the pickup event: react the instant the trident is grabbed.
TridentSpawner.ItemPickedUpEvent.Subscribe(OnTridentPickedUp)
# -------------------------------------------------------
# Called when a player steps onto the dock pressure plate.
# TriggeredEvent sends ?agent, so we unwrap it.
# -------------------------------------------------------
OnDockEntered(MaybeAgent : ?agent) : void =
# Enable the spawner so it can produce items.
TridentSpawner.Enable()
# Explicitly spawn the current item (the trident, slot 0 in the item list).
TridentSpawner.SpawnItem()
# Disable the pressure plate so it only fires once per round.
DockTrigger.Disable()
# -------------------------------------------------------
# Called the moment any player picks up the trident.
# ItemPickedUpEvent sends agent (non-optional).
# -------------------------------------------------------
OnTridentPickedUp(PickupAgent : agent) : void =
# Lock the spawner — no duplicate tridents.
TridentSpawner.Disable()
# Play the kraken cinematic for everyone.
KrakenCinematic.Play()
# After the cinematic, reconfigure and re-enable the spawner
# so a second player can eventually get loot.
spawn { ReconfigureSpawnerAfterCinematic() }
# -------------------------------------------------------
# Async helper — waits for the cinematic to finish,
# then sets a longer respawn timer and cycles to the next item.
# -------------------------------------------------------
ReconfigureSpawnerAfterCinematic()<suspends> : void =
# Block until the cinematic sequence stops.
KrakenCinematic.StoppedEvent.Await()
# Switch to the next item in the spawner's list (healing fish, slot 1).
TridentSpawner.CycleToNextItem()
# Turn on the automatic respawn timer...
TridentSpawner.SetEnableRespawnTimer(true)
# ...and set it to 60 seconds so the next drop feels earned.
TridentSpawner.SetTimeBetweenSpawns(60.0)
# Re-enable the spawner — it will now auto-respawn the healing fish.
TridentSpawner.Enable()
# Re-enable the pressure plate for the next player.
DockTrigger.Enable()
Line-by-line explanation
| Lines | What's happening |
|---|---|
@editable fields |
Declare every placed device as an editable field — this is the only way Verse can talk to a device you placed in UEFN. |
TridentSpawner.Disable() in OnBegin |
The chest starts empty; nothing spawns until a player earns it. |
DockTrigger.TriggeredEvent.Subscribe(OnDockEntered) |
Hooks the pressure-plate event to our handler. |
TridentSpawner.ItemPickedUpEvent.Subscribe(OnTridentPickedUp) |
Hooks the pickup event — note this event sends a plain agent, not ?agent. |
OnDockEntered(MaybeAgent : ?agent) |
TriggeredEvent sends ?agent; we accept it but don't need to unwrap it here because we're acting on the spawner, not the agent. |
TridentSpawner.SpawnItem() |
Forces the item to appear immediately rather than waiting for the editor timer. |
KrakenCinematic.StoppedEvent.Await() |
Suspends the coroutine until the cinematic finishes — clean sequencing without a Sleep hack. |
CycleToNextItem() |
Advances the spawner's internal item pointer to slot 1 (healing fish). |
SetEnableRespawnTimer(true) + SetTimeBetweenSpawns(60.0) |
Turns on auto-respawn and sets the delay to 60 seconds at runtime. |
Common patterns
Pattern 1 — Timed wave loot (enable respawn timer from code)
A clifftop arena drops a new weapon every 20 seconds once the round starts. The spawner is disabled at game start and enabled by a countdown timer.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
clifftop_wave_loot := class(creative_device):
# Item spawner placed on the clifftop arena floor.
@editable WaveSpawner : item_spawner_device = item_spawner_device{}
OnBegin<override>()<suspends> : void =
# Wait 10 seconds for the round to settle before the first drop.
Sleep(10.0)
# Enable auto-respawn and set the cadence to 20 seconds.
WaveSpawner.SetEnableRespawnTimer(true)
WaveSpawner.SetTimeBetweenSpawns(20.0)
# Confirm the current settings (useful for debugging).
var CurrentDelay : float = WaveSpawner.GetTimeBetweenSpawns()
# Enable the device — it will now spawn and auto-respawn every 20 s.
WaveSpawner.Enable()
# Force the very first item to appear immediately.
WaveSpawner.SpawnItem()
Pattern 2 — Cycling items on each pickup (rotating loot table)
A lagoon shrine cycles through three items — trident, healing fish, cannonball — so every player who visits gets something different.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
lagoon_shrine_loot := class(creative_device):
# Item spawner at the lagoon shrine.
@editable ShrineSpawner : item_spawner_device = item_spawner_device{}
OnBegin<override>()<suspends> : void =
# Spawn the first item immediately.
ShrineSpawner.SpawnItem()
# Each time someone picks up, advance to the next item and respawn.
ShrineSpawner.ItemPickedUpEvent.Subscribe(OnShrineItemPickedUp)
OnShrineItemPickedUp(PickupAgent : agent) : void =
# Advance the item list pointer (wraps around automatically).
ShrineSpawner.CycleToNextItem()
# Spawn the new item straight away — no timer needed.
ShrineSpawner.SpawnItem()
Pattern 3 — Disable spawner when a zone is contested (Enable / Disable + trigger)
A shore capture zone disables the nearby ammo spawner while contested, re-enabling it only when the zone is clear. Uses a second trigger to simulate the "zone cleared" signal.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
shore_ammo_controller := class(creative_device):
# Ammo crate spawner on the shore.
@editable AmmoSpawner : item_spawner_device = item_spawner_device{}
# Trigger fires when the capture zone becomes contested.
@editable ZoneContestedTrigger : trigger_device = trigger_device{}
# Trigger fires when the capture zone is cleared.
@editable ZoneClearedTrigger : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
ZoneContestedTrigger.TriggeredEvent.Subscribe(OnZoneContested)
ZoneClearedTrigger.TriggeredEvent.Subscribe(OnZoneCleared)
# Ammo starts available.
AmmoSpawner.Enable()
AmmoSpawner.SpawnItem()
OnZoneContested(MaybeAgent : ?agent) : void =
# No free ammo while the zone is being fought over.
AmmoSpawner.Disable()
OnZoneCleared(MaybeAgent : ?agent) : void =
# Zone is safe — restore ammo and spawn immediately.
AmmoSpawner.Enable()
AmmoSpawner.SpawnItem()
Gotchas
1. Always declare devices as @editable class fields
You cannot write item_spawner_device{}.SpawnItem() in a function body and expect it to control a placed device. Every device you place in UEFN must be exposed as an @editable field on your creative_device class, then wired up in the Details panel. A bare local variable is a brand-new, unplaced instance with no world presence.
2. ItemPickedUpEvent sends agent, not ?agent
TriggeredEvent on a trigger_device sends ?agent (optional — it can fire without a player). ItemPickedUpEvent on item_spawner_device sends a plain agent — no optional unwrap needed. Mixing these up causes a type error.
# CORRECT — ItemPickedUpEvent handler
OnItemPickedUp(PickupAgent : agent) : void =
# use PickupAgent directly
# CORRECT — TriggeredEvent handler
OnTriggered(MaybeAgent : ?agent) : void =
if (A := MaybeAgent?):
# use A
3. SetTimeBetweenSpawns only matters when the respawn timer is enabled
Calling SetTimeBetweenSpawns(5.0) has no effect unless SetEnableRespawnTimer(true) has also been called (or the device's Respawn Item on Timer option is checked in the editor). Always pair the two calls.
4. SpawnItem() does not reset the respawn countdown
If you call SpawnItem() manually while the respawn timer is also running, you can end up with overlapping spawns. Either disable the respawn timer when manually spawning, or use one approach consistently per spawner.
5. No int ↔ float auto-conversion
SetTimeBetweenSpawns takes a float. Passing an integer literal like 30 will cause a type error — always write 30.0.
6. CycleToNextItem wraps silently
When the spawner reaches the last item in its list, the next CycleToNextItem() call wraps back to item 0. There is no event or return value to tell you which slot is currently active, so design your item lists with wrap-around in mind.
7. Localized text for UI messages
If you display a message (e.g. via a hud_message_device) when the item spawns, remember that message parameters require a localized value — declare a helper:
PickupMsg<localizes>(S : string) : message = "{S}"
There is no StringToMessage function in Verse.