Overview
The collectible_object_device represents a single collectible item placed in the world — think a glowing orb, a coin, a key, or any pickup your game needs. Out of the box the device handles its own pickup detection; your Verse code just subscribes to CollectedEvent and decides what happens next.
When to reach for it:
- Scavenger hunts where items must be found in order
- Score-based games where grabbing a pickup awards points
- Timed respawn loops — items vanish when grabbed and reappear after a delay
- Puzzle gates — collect all items to unlock a door
The three methods give you full lifecycle control:
| Goal | Call |
|---|---|
| Make the item appear | Show() |
| Make the item disappear (uncollected) | Hide() |
| Instantly respawn for every player | RespawnForAll() |
And CollectedEvent fires the moment any agent picks the item up, handing you the collecting agent so you can award score, play feedback, or trigger the next phase.
API Reference
collectible_object_device
Used to place a collectible item into the world.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
collectible_object_device<public> := class<concrete><final>(creative_device_base):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
CollectedEvent |
CollectedEvent<public>:listenable(agent) |
Signaled when the collectible item is collected. Sends the agent that collected the item. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Show |
Show<public>():void |
Makes the collectible visible. |
Hide |
Hide<public>():void |
Makes the collectible invisible. |
RespawnForAll |
RespawnForAll<public>():void |
Immediately respawns the object for all agents. |
Walkthrough
Scenario: A timed scavenger-hunt orb. The orb starts hidden, appears when the round begins, fires a congratulations message when collected, and automatically respawns for all players 5 seconds later so the hunt never stops.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Localized helper so we can pass text to Print (core built-in)
HuntMessage<localizes>(S : string) : message = "{S}"
scavenger_hunt_manager := class(creative_device):
# Wire this to your Collectible Object Device in the UEFN editor
@editable
Orb : collectible_object_device = collectible_object_device{}
# Seconds before the orb respawns after being collected
@editable
RespawnDelay : float = 5.0
OnBegin<override>()<suspends> : void =
# Hide the orb at start — the round reveal will Show it
Orb.Hide()
# Wait a moment for the round to "start", then reveal the orb
Sleep(3.0)
Orb.Show()
# Subscribe to collection so we react every time someone grabs it
Orb.CollectedEvent.Subscribe(OnOrbCollected)
# Keep the game running indefinitely
loop:
Sleep(60.0)
# Called each time an agent collects the orb
OnOrbCollected(Collector : agent) : void =
# Hide immediately so no one else can grab the same instance
Orb.Hide()
# Spawn an async task to respawn after the delay
spawn { RespawnAfterDelay() }
# Waits RespawnDelay seconds then brings the orb back for everyone
RespawnAfterDelay()<suspends> : void =
Sleep(RespawnDelay)
Orb.RespawnForAll()
Orb.Show()
Line-by-line explanation:
@editable Orb— exposes the device slot in the UEFN editor so you can drag your placed Collectible Object Device onto it. Without this the Verse class has no reference to the actual device.Orb.Hide()— called immediately inOnBeginso the orb is invisible until the round starts.Sleep(3.0)— a simple countdown before the hunt begins. BecauseOnBeginis<suspends>we canSleepfreely.Orb.Show()— reveals the orb in the world, making it collectable.Orb.CollectedEvent.Subscribe(OnOrbCollected)— registers our handler. Every future collection callsOnOrbCollected.OnOrbCollected(Collector : agent)— the handler signature matcheslistenable(agent): the parameter is a plainagent, not?agent, so no unwrapping is needed here.Orb.Hide()inside the handler — immediately hides the orb so it cannot be double-collected while the respawn timer runs.spawn { RespawnAfterDelay() }— launches the delay as a concurrent task so the handler returns instantly.Orb.RespawnForAll()— resets the collectible's internal state for every player, thenShow()makes it visible again.
Common patterns
Pattern 1 — Hide the orb until a button is pressed
A vault door scenario: the collectible key is hidden until a guard button is pressed, then it appears.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
key_reveal_manager := class(creative_device):
@editable
KeyOrb : collectible_object_device = collectible_object_device{}
@editable
GuardButton : button_device = button_device{}
OnBegin<override>()<suspends> : void =
# Key starts hidden — players cannot grab it yet
KeyOrb.Hide()
# Reveal the key the moment the guard button is pressed
GuardButton.InteractedWithEvent.Subscribe(OnGuardButtonPressed)
loop:
Sleep(60.0)
OnGuardButtonPressed(Interactor : agent) : void =
# Show the collectible so players can now pick it up
KeyOrb.Show()
Pattern 2 — Award score on collection and respawn for all
A coin-rush mode: every player who grabs the coin gets a score bump, then the coin instantly reappears for everyone.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Fortnite.com/Characters }
using { /Fortnite.com/Game }
coin_rush_manager := class(creative_device):
@editable
Coin : collectible_object_device = collectible_object_device{}
@editable
ScoreManager : score_manager_device = score_manager_device{}
OnBegin<override>()<suspends> : void =
Coin.Show()
Coin.CollectedEvent.Subscribe(OnCoinCollected)
loop:
Sleep(60.0)
OnCoinCollected(Collector : agent) : void =
# Award 10 points to whoever grabbed the coin
ScoreManager.SetScoreForPlayer(Collector, ScoreManager.GetCurrentScore(Collector) + 10)
# Immediately bring the coin back for every player
Coin.RespawnForAll()
Pattern 3 — React to the collecting agent with an option-safe unwrap
Some event sources send ?agent (optional). While CollectedEvent sends a plain agent, here is the safe pattern for when you forward the agent into a context that returns an optional — for example, casting to fort_character.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Fortnite.com/Characters }
character_react_manager := class(creative_device):
@editable
PowerOrb : collectible_object_device = collectible_object_device{}
OnBegin<override>()<suspends> : void =
PowerOrb.Show()
PowerOrb.CollectedEvent.Subscribe(OnPowerOrbCollected)
loop:
Sleep(60.0)
OnPowerOrbCollected(Collector : agent) : void =
# Cast agent to fort_character — this is failable, so use if
if (Character := Collector.GetFortCharacter[]):
# Hide the orb for a dramatic moment, then respawn it
PowerOrb.Hide()
spawn { RevealAfterDelay() }
RevealAfterDelay()<suspends> : void =
Sleep(4.0)
PowerOrb.RespawnForAll()
PowerOrb.Show()
Gotchas
1. Always declare the device as @editable.
You cannot construct a collectible_object_device{} and have it refer to a placed device. The @editable attribute is what binds your Verse field to the actual device placed in the UEFN level. Forgetting it means Orb.Show() silently operates on a default, unplaced instance.
2. CollectedEvent sends agent, not ?agent.
The handler signature is OnCollected(Collector : agent) : void, NOT (Collector : ?agent). Trying to unwrap with if (A := Collector?) is a compile error because Collector is already a concrete agent.
3. Hide() does not reset the collectible's internal "collected" state — RespawnForAll() does.
If you only call Hide() after collection and then Show() later, players who already collected it may not be able to pick it up again (depending on the device's Consume If Collected By setting). Always pair Hide() with a subsequent RespawnForAll() when you want the item to be re-collectable.
4. RespawnForAll() is instant — use Sleep before it for timed respawns.
Calling RespawnForAll() immediately after Hide() in the same frame can cause a visual flicker. Wrap the respawn in a <suspends> helper and Sleep for your desired delay, as shown in the Walkthrough.
5. spawn {} is required for async work inside event handlers.
Event handlers (subscribed via Subscribe) are NOT <suspends> — you cannot call Sleep directly inside them. Always use spawn { MyAsyncHelper() } to launch any coroutine from a handler.
6. Localized text for message parameters.
If you ever pass text to a device method that expects a message type (e.g., HUD devices), you cannot pass a raw string. Declare a localizer function: MyText<localizes>(S : string) : message = "{S}" and call MyText("Hello").