Overview
GetRandomFloat is a pure Verse function (not a placed device) that returns a pseudo-random float value between two bounds you supply. It is your go-to tool whenever you need non-deterministic numbers at runtime: randomised delays, variable damage amounts, procedural spawn offsets, weighted probability checks, and anything else that should feel different every time a player experiences it.
When to reach for it:
- You want a platform to reappear after a random delay (e.g. 2–6 seconds).
- You want to award a random score bonus within a range.
- You want to randomly choose between two outcomes by comparing the result to a threshold (e.g.
< 0.5= heads,>= 0.5= tails). - You need a float offset to scatter prop positions or vary cinematic timing.
It is not a placed UEFN device — you never drag it onto the island. You just using { /Verse.org/Random } and call it.
API Reference
(API surface could not be resolved for this device.)
Walkthrough
Scenario: The Drifting Cove Timer
You are building a sunny clifftop cove challenge. A player steps onto a pressure plate at the dock. A countdown timer starts — but the duration is randomised between 8 and 20 seconds so veterans can't memorise the window. When the timer succeeds (player survives), they earn a score bonus. When it fails, a cinematic "wave crash" sequence plays.
This example wires together GetRandomFloat, timer_device, score_manager_device, and cinematic_sequence_device — all driven by a trigger_device on the dock.
using { /Fortnite.com/Devices }
using { /Verse.org/Random }
using { /Verse.org/Simulation }
# cove_challenge_device
# Place this Verse device on your island, then assign the four
# @editable fields in the Details panel.
cove_challenge_device := class(creative_device):
# The pressure plate on the dock the player steps on.
@editable DockTrigger : trigger_device = trigger_device{}
# A timer device whose *Duration* property is ignored at runtime —
# we reset and start it programmatically with a random window.
@editable ChallengeTimer : timer_device = timer_device{}
# Awards points when the player survives the wave window.
@editable ScoreManager : score_manager_device = score_manager_device{}
# A cinematic sequence of a giant wave crashing over the cove.
@editable WaveCrashSequence : cinematic_sequence_device = cinematic_sequence_device{}
# --- lifecycle ---
OnBegin<override>()<suspends>:void =
# Subscribe to the dock trigger so we know when a player steps on.
DockTrigger.TriggeredEvent.Subscribe(OnPlayerSteppedOnDock)
# Subscribe to timer outcomes.
ChallengeTimer.SuccessEvent.Subscribe(OnTimerSuccess)
ChallengeTimer.FailureEvent.Subscribe(OnTimerFailure)
# --- event handlers ---
# Called when any agent steps on the dock trigger.
OnPlayerSteppedOnDock(MaybeAgent : ?agent) : void =
if (Agent := MaybeAgent?):
# Pick a random challenge window: anywhere from 8 to 20 seconds.
# GetRandomFloat(Min, Max) returns a float in [Min, Max].
RandomDuration : float = GetRandomFloat(8.0, 20.0)
# Reset the timer to its base state, then give it a head-start
# delay equal to our random duration using Sleep on a spawned task.
ChallengeTimer.Reset(Agent)
ChallengeTimer.Start(Agent)
# Spawn a concurrent task that stops the timer after RandomDuration
# seconds — this is how we inject the random window.
spawn { WaitThenForceTimerEnd(Agent, RandomDuration) }
WaitThenForceTimerEnd(Agent : agent, Duration : float)<suspends> : void =
# Sleep for the random duration, then stop the timer.
# If the timer already fired SuccessEvent, Pause is a no-op.
Sleep(Duration)
ChallengeTimer.Pause(Agent)
# Timer reached its configured end before we stopped it — player survived!
OnTimerSuccess(MaybeAgent : ?agent) : void =
if (A := MaybeAgent?):
ScoreManager.Activate(A)
# Timer was stopped externally (wave arrived) — play the crash cinematic.
OnTimerFailure(MaybeAgent : ?agent) : void =
WaveCrashSequence.Play()```
### Line-by-line highlights
| Line | What it does |
|---|---|
| `using { /Verse.org/Random }` | Brings `GetRandomFloat` into scope — without this the compiler reports *Unknown identifier*. |
| `GetRandomFloat(8.0, 20.0)` | Returns a random `float` in the closed interval [8.0, 20.0]. Both bounds are inclusive. |
| `spawn { WaitThenForceTimerEnd(...) }` | Fires the async helper concurrently so `OnPlayerSteppedOnDock` returns immediately. |
| `Sleep(Duration)` | Suspends the spawned coroutine for exactly the random number of seconds we chose. |
| `if (A := MaybeAgent?)` | Safely unwraps the `?agent` the timer events send — required before calling `ScoreManager.Activate`. |
| `WaveCrashSequence.Play()` | Triggers the cinematic with no instigator (set device to *Everyone* in its properties). |
---
## Common patterns
### Pattern 1 — Coin-flip probability gate
Use `GetRandomFloat(0.0, 1.0)` as a probability value. Anything below your threshold takes one branch; anything above takes the other. Here a 30 % chance awards bonus points at the clifftop chest.
```verse
using { /Fortnite.com/Devices }
using { /Verse.org/Random }
cove_bonus_device := class(creative_device):
@editable ChestTrigger : trigger_device = trigger_device{}
@editable BonusScore : score_manager_device = score_manager_device{}
@editable JackpotSequence : cinematic_sequence_device = cinematic_sequence_device{}
OnBegin<override>()<suspends>:void =
ChestTrigger.TriggeredEvent.Subscribe(OnChestOpened)
OnChestOpened(Agent : agent) : void =
# Roll between 0.0 and 1.0.
Roll : float = GetRandomFloat(0.0, 1.0)
# 30 % jackpot chance.
if (Roll < 0.3):
BonusScore.Activate(Agent)
JackpotSequence.Play(Agent)
else:
# Normal score — no cinematic.
BonusScore.Activate(Agent)
Pattern 2 — Random respawn delay at a shore spawner
After a player is eliminated, wait a random 3–7 seconds before respawning them at the cove shore. This keeps the timing unpredictable and prevents spawn-camping patterns.
using { /Fortnite.com/Devices }
using { /Verse.org/Random }
using { /Verse.org/Simulation }
cove_respawn_device := class(creative_device):
@editable ShoreSpawner : player_spawner_device = player_spawner_device{}
@editable EliminationTrigger : trigger_device = trigger_device{}
OnBegin<override>()<suspends>:void =
EliminationTrigger.TriggeredEvent.Subscribe(OnPlayerEliminated)
OnPlayerEliminated(Agent : agent) : void =
spawn { DelayedRespawn(Agent) }
DelayedRespawn(Agent : agent)<suspends> : void =
# Random wait between 3 and 7 seconds before the shore respawn.
Delay : float = GetRandomFloat(3.0, 7.0)
Sleep(Delay)
if (P := player[Agent]):
ShoreSpawner.SpawnPlayer(P)
Pattern 3 — Scaled random score increment
Call GetRandomFloat to decide how many times to increment a score manager before activating it — giving a variable bonus between 1 and 5 extra points. This uses the integer conversion pattern (Floor from /Verse.org/SpatialMath is unavailable here, so we use the range directly with a cast-safe approach via repeated Increment).
using { /Fortnite.com/Devices }
using { /Verse.org/Random }
using { /Verse.org/Simulation }
cove_variable_score_device := class(creative_device):
@editable DockTrigger : trigger_device = trigger_device{}
@editable ScoreManager : score_manager_device = score_manager_device{}
OnBegin<override>()<suspends>:void =
DockTrigger.TriggeredEvent.Subscribe(OnDockReached)
OnDockReached(Agent : agent) : void =
# Random float in [1.0, 5.0]; truncate to int via comparison steps.
BonusFloat : float = GetRandomFloat(1.0, 5.0)
# Increment the score manager 1–5 extra times based on the random value.
# Each Increment raises the next Activate payout by 1.
if (BonusFloat >= 2.0): ScoreManager.Increment(Agent)
if (BonusFloat >= 3.0): ScoreManager.Increment(Agent)
if (BonusFloat >= 4.0): ScoreManager.Increment(Agent)
if (BonusFloat >= 5.0): ScoreManager.Increment(Agent)
# Award the accumulated score.
ScoreManager.Activate(Agent)
Gotchas
1. Missing using { /Verse.org/Random } → Unknown identifier: GetRandomFloat
This is the #1 compile error. GetRandomFloat lives in /Verse.org/Random, not in the default Verse scope. Always add the using directive.
2. Bounds are floats — no int literals
GetRandomFloat(1, 5) will not compile because 1 and 5 are int literals and Verse does not auto-convert int to float. Always write 1.0 and 5.0.
3. Min must be ≤ Max
Passing GetRandomFloat(10.0, 2.0) (min > max) produces undefined behaviour. Always double-check your bounds order, especially when they come from @editable fields.
4. ?agent unwrap in timer/trigger events
Events like timer_device.SuccessEvent send ?agent (an optional). You must unwrap with if (A := MaybeAgent?): before passing the agent to functions like ScoreManager.Activate(A). Skipping the unwrap is a compile error.
5. GetRandomFloat is not <suspends> — no Sleep needed
The function returns synchronously. You only need Sleep when you want to wait for the random duration, not to call GetRandomFloat itself.
6. Localized message params are not strings
If you want to display the random value in a UI label, you cannot pass a raw float or string directly to a message parameter. Declare a localizes helper: MyLabel<localizes>(V:string):message = "{V}" and convert via string interpolation. There is no FloatToMessage or StringToMessage built-in.