Overview
The player_counter_device solves a classic party-game problem: "don't start until enough players are ready." Place it on a sun-bleached dock, a cove platform, or a clifftop arena, and it continuously compares the number of players standing inside its zone against a configurable Target Player Count. When the count is met it fires CountSucceedsEvent; if players leave and the count drops it fires CountFailsEvent. Individual arrivals and departures are reported through CountedEvent and RemovedEvent.
Reach for player_counter_device when you need:
- A lobby gate that unlocks a mini-game only when the right number of players are present.
- A "waiting area" that starts a countdown timer once enough crew members arrive.
- Dynamic target adjustments mid-game (e.g., reduce the required count after a player disconnects).
API Reference
(API surface could not be resolved for this device.)
Walkthrough
Scenario — Dock Departure: Four players must stand on the wooden dock before the boat-launch cinematic plays and a timer starts. If players leave before the sequence finishes, the timer resets and the cinematic stops.
using { /UnrealEngine.com/Temporary/UI }
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
# Place this device in your UEFN level alongside a player_counter_device,
# a cinematic_sequence_device, and a timer_device.
dock_departure_manager := class(creative_device):
# Wire up in the UEFN Details panel
@editable
DockCounter : player_counter_device = player_counter_device{}
@editable
BoatLaunchCinematic : cinematic_sequence_device = cinematic_sequence_device{}
@editable
DepartureTimer : timer_device = timer_device{}
# Called once when the island session begins
OnBegin<override>()<suspends> : void =
# Subscribe to all three counter events
DockCounter.CountSucceedsEvent.Subscribe(OnCountSucceeds)
DockCounter.CountFailsEvent.Subscribe(OnCountFails)
DockCounter.CountedEvent.Subscribe(OnPlayerCounted)
# Fires when the zone reaches (or exceeds) Target Player Count
# CountSucceedsEvent sends tuple() — no payload to unwrap
OnCountSucceeds(Ignored : tuple()) : void =
# Enough players on the dock — play the boat-launch cinematic
BoatLaunchCinematic.Play()
# Start the departure countdown for everyone
DepartureTimer.Start()
# Fires when the zone drops below Target Player Count
OnCountFails(Ignored : tuple()) : void =
# Someone left — abort the launch sequence
BoatLaunchCinematic.Stop()
DepartureTimer.Reset()
# Reset the counter's target back to its default (4 players)
DockCounter.Reset()
# Fires each time a single valid player enters the zone
# CountedEvent sends the agent who just stepped in
OnPlayerCounted(NewCrew : agent) : void =
# Show the info panel so players can see Current vs Required count
DockCounter.ShowInfoPanel()
Line-by-line breakdown:
| Lines | What's happening |
|---|---|
@editable fields |
Lets you wire the three devices in the UEFN Details panel — required for any placed device reference. |
OnBegin |
The only safe place to subscribe to events; runs once at session start. |
CountSucceedsEvent.Subscribe(OnCountSucceeds) |
Registers OnCountSucceeds to be called whenever the zone headcount meets the target. |
BoatLaunchCinematic.Play() |
Triggers the boat-launch level sequence for everyone. |
DepartureTimer.Start() |
Kicks off the countdown — players now race against the clock. |
OnCountFails |
Handles the "someone bailed" case: stops the cinematic, resets the timer, and resets the counter's target to its editor default. |
OnPlayerCounted |
Receives the individual agent who just entered; calls ShowInfoPanel() so the HUD updates immediately. |
Common patterns
Pattern 1 — Dynamically lower the required count mid-game
If a player disconnects, use DecrementTargetCount() so the remaining crew aren't stuck waiting forever.
using { /UnrealEngine.com/Temporary/UI }
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
dynamic_target_manager := class(creative_device):
@editable
DockCounter : player_counter_device = player_counter_device{}
OnBegin<override>()<suspends> : void =
# When a player is removed from the count (left the zone or disconnected)
DockCounter.RemovedEvent.Subscribe(OnPlayerRemoved)
# RemovedEvent sends the agent who is no longer counted
OnPlayerRemoved(LeavingPlayer : agent) : void =
# Lower the bar by 1 so the remaining players can still succeed
DockCounter.DecrementTargetCount()
# Refresh the HUD so everyone sees the new requirement
DockCounter.ShowInfoPanel()
Pattern 2 — Broadcast to all currently counted players at once
Use TransmitForAllCounted() to re-fire CountedEvent for every agent already in the zone — handy for late-join initialization.
using { /UnrealEngine.com/Temporary/UI }
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
late_join_initializer := class(creative_device):
@editable
DockCounter : player_counter_device = player_counter_device{}
@editable
ScoreManager : score_manager_device = score_manager_device{}
OnBegin<override>()<suspends> : void =
DockCounter.CountedEvent.Subscribe(OnPlayerCounted)
# After a short wait, ping all already-counted players
# so they receive their starting bonus too
Sleep(5.0)
DockCounter.TransmitForAllCounted()
OnPlayerCounted(Player : agent) : void =
# Award a "you made it to the dock" bonus point
ScoreManager.Activate(Player)
Pattern 3 — Raise the required count for a harder challenge
Use SetTargetCount() to change the target on the fly — for example, scale difficulty with the number of players who joined the session.
using { /UnrealEngine.com/Temporary/UI }
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
scalable_challenge_manager := class(creative_device):
@editable
DockCounter : player_counter_device = player_counter_device{}
@editable
BoatLaunchCinematic : cinematic_sequence_device = cinematic_sequence_device{}
OnBegin<override>()<suspends> : void =
DockCounter.CountSucceedsEvent.Subscribe(OnCountSucceeds)
# Example: require ALL 8 players for the grand finale
DockCounter.SetTargetCount(8)
DockCounter.ShowInfoPanel()
OnCountSucceeds(Ignored : tuple()) : void =
# Full crew on deck — fire the grand finale cinematic
BoatLaunchCinematic.Play()
Gotchas
CountSucceedsEvent and CountFailsEvent send tuple(), not agent.
Their handlers must accept (Ignored : tuple()). A common mistake is writing (A : agent) — that won't compile.
CountedEvent and RemovedEvent send a plain agent, not ?agent.
No optional unwrap needed here. Just use the value directly: OnPlayerCounted(NewCrew : agent).
Reset() restores the editor-configured target, not zero.
If you called SetTargetCount(8) at runtime and then call Reset(), the target snaps back to whatever you set in the UEFN Details panel — not 8. Store your runtime target in a var if you need to restore it.
DecrementTargetCount() can push the target below 1.
Guard against this if players keep leaving: check your game logic before calling it repeatedly, or you may end up with a target of 0 or negative, which immediately triggers CountSucceedsEvent.
ShowInfoPanel() is a one-shot display call.
It shows the panel at that moment; it does not keep it permanently visible. Call it again whenever the count changes if you want the HUD to stay current.
The device must be enabled to count players.
If you disabled it earlier in your flow (e.g., between rounds), call Enable() before expecting any count events to fire.
@editable is mandatory for all placed device references.
You cannot write player_counter_device{} and expect it to reference the one you placed on the island. Every device used in Verse must be declared as an @editable field and wired in the Details panel.