Overview
The word range in UEFN Verse covers two related but distinct ideas:
- Integer range expressions — the
rangetype, writtenMin..Max, that lets you iterate over a contiguous series of integers with aforloop. This is a core Verse language feature, not a device. - Float
Rangefields — distance values (in centimetres) that appear on weapon components (e.g.fort_trace_weapon_component) and AI devices (e.g.guard_spawner_device.VisibilityRange). These control how far a mechanic reaches in 3-D space.
When to reach for each
| You want to… | Use… |
|---|---|
| Loop over indices 0 to N | for (I := 0..N-1) |
| Activate N devices in sequence | integer range + array index |
| Set how far a guard can see | GuardSpawner.VisibilityRange (float) |
| Tweak weapon effective distance | fort_trace_weapon_component.Range (float) |
Both ideas show up constantly in real island scripting, so this article covers both with a concrete dock/shore scenario.
API Reference
(API surface could not be resolved for this device.)
Walkthrough
The scenario
You're building a Smuggler's Dock island. A row of five warning buoys lines the pier. When the round starts, the buoys light up one by one (integer range loop), and a guard spawner's visibility range is set based on whether it's day or night — wide open during the day, tighter at night so players can sneak past.
Level setup
- Place 5 × Conditional Button devices (used here as buoy-light proxies) and wire them into the
BuoyLightsarray. - Place 1 × Guard Spawner device and assign it to
DockGuard. - Place 1 × Class Selector device (acts as the day/night toggle) assigned to
DayNightToggle.
using { /Fortnite.com/Devices }
using { /Fortnite.com/AI }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# smugglers_dock_controller — lights up buoys one by one, then sets guard
# visibility range based on time of day.
dock_controller := class(creative_device):
# Five buoy-light devices placed along the pier.
@editable
BuoyLights : []button_device = array{}
# The guard spawner watching the dock.
@editable
DockGuard : guard_spawner_device = guard_spawner_device{}
# Class selector used as a day/night toggle.
# When option A is chosen = day; option B = night.
@editable
DayNightToggle : class_and_team_selector_device = class_and_team_selector_device{}
# Visibility range (cm) during the day — guards spot players at 15 m.
DayVisibilityRange : float = 1500.0
# Visibility range (cm) at night — only 6 m, perfect for sneaking.
NightVisibilityRange : float = 600.0
# Track whether it is currently daytime.
var IsDaytime : logic = true
OnBegin<override>()<suspends> : void =
# Subscribe to the day/night toggle so we can react to changes.
DayNightToggle.ClassSwitchedEvent.Subscribe(OnTimeOfDayChanged)
# Light up the buoys one by one using an integer range.
# 0..4 produces the integers 0, 1, 2, 3, 4 — one per buoy.
for (Index := 0..4):
if (Light := BuoyLights[Index]):
Light.Enable() # turn the buoy light on
Sleep(0.4) # brief pause for a ripple effect
# Apply the starting (daytime) visibility range to the guard.
ApplyVisibilityRange()
# Spawn the guard now that the scene is set.
DockGuard.Enable()
# Called whenever the day/night class selector fires.
OnTimeOfDayChanged(Agent : agent) : void =
# Toggle the time-of-day flag.
if (IsDaytime?):
set IsDaytime = false
else:
set IsDaytime = true
ApplyVisibilityRange()
# Push the correct float Range value to the guard spawner.
ApplyVisibilityRange() : void =
if (IsDaytime?):
# Daytime — guards have a long sight line across the sunny dock.
set DockGuard.VisibilityRange = DayVisibilityRange
else:
# Night — reduced range lets players sneak along the shore.
set DockGuard.VisibilityRange = NightVisibilityRange```
### Line-by-line explanation
| Lines | What's happening |
|---|---|
| `@editable BuoyLights` | An array of `button_device` — each represents one buoy light on the pier. |
| `@editable DockGuard` | The `guard_spawner_device` whose `VisibilityRange` float field we'll mutate. |
| `for (Index := 0..4)` | **Integer range** — Verse iterates Index through 0, 1, 2, 3, 4. |
| `BuoyLights[Index]` | Array subscript using the range index; returns `?button_device`, unwrapped with `if`. |
| `Sleep(0.4)` | Suspends the coroutine briefly so lights appear to ripple outward. |
| `set DockGuard.VisibilityRange = DayVisibilityRange` | Writes the **float Range field** — 1500 cm = 15 m of guard sight. |
| `DockGuard.Enable()` | Spawns the guard after the scene is ready. |
## Common patterns
### Pattern 1 — Counting down with a reverse integer range
A countdown timer that ticks from 5 to 1 before the boat leaves the dock.
```verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
dock_countdown := class(creative_device):
@editable
HudMessage : hud_message_device = hud_message_device{}
CountdownText<localizes>(N : int) : message = "Boat leaves in {N}..."
OnBegin<override>()<suspends> : void =
# Iterate 5 down to 1 using a range and array reverse trick.
# Verse ranges are always ascending, so we subtract from 5.
for (Step := 0..4):
Remaining := 5 - Step
HudMessage.SetText(CountdownText(Remaining))
HudMessage.Show()
Sleep(1.0)
HudMessage.Hide()
Why
0..4and not5..1? Verse integer ranges are always ascending —5..1produces no iterations. Subtract from your max value to count down.
Pattern 2 — Tightening a guard's visibility range progressively (float Range)
As a fog-of-war storm rolls in from the sea, the guard's sight line shrinks every 10 seconds.
using { /Fortnite.com/Devices }
using { /Fortnite.com/AI }
using { /Verse.org/Simulation }
fog_controller := class(creative_device):
@editable
ShoreGuard : guard_spawner_device = guard_spawner_device{}
# Start at 2000 cm (20 m), shrink by 300 cm each tick, floor at 400 cm.
OnBegin<override>()<suspends> : void =
# Use an integer range to drive 6 fog-thickening steps (0..5).
for (Step := 0..5):
NewRange : float = 2000.0 - (300.0 * Step)
# Clamp so we never go below 400 cm — guards still notice
# players right next to them even in thick fog.
ClampedRange : float =
if (NewRange >= 400.0) then NewRange else 400.0
set ShoreGuard.VisibilityRange = ClampedRange
Sleep(10.0)
This pattern combines both range ideas: an integer range drives the loop steps, and a float
VisibilityRangefield is updated each iteration.
Pattern 3 — Iterating a range to reset multiple devices
After a round ends at the clifftop arena, reset all five capture pads in one clean loop.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
clifftop_reset := class(creative_device):
@editable
CapturePads : []capture_area_device = array{}
@editable
RoundEndTrigger : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
RoundEndTrigger.TriggeredEvent.Subscribe(OnRoundEnd)
OnRoundEnd(Agent : ?agent) : void =
# Reset every capture pad using a range over the array length.
LastIndex := CapturePads.Length - 1
if (LastIndex >= 0):
for (I := 0..LastIndex):
if (Pad := CapturePads[I]):
Pad.Reset()
Gotchas
1. Verse ranges are always ascending
Writing 5..1 compiles but produces zero iterations — the loop body never runs. To count downward, iterate 0..N and compute N - Index inside the body.
2. Integer range vs. float Range — completely different things
0..4 is a language-level iterator. guard_spawner_device.VisibilityRange is a var float field on a device. They share a name in English but have no connection in the type system. Don't try to assign a range expression to a float field.
3. VisibilityRange is clamped by the engine
The guard spawner clamps VisibilityRange between 0.0 and 25000.0 cm. Values outside that window are silently clamped — you won't get a compile or runtime error, the value just won't go higher than 250 m.
4. Array subscript returns an option
BuoyLights[Index] has type ?button_device. Always unwrap it:
if (Light := BuoyLights[Index]):
Light.SetEnabled(true)
Skipping the if is a compile error — Verse won't let you call methods on an option type directly.
5. Sleep requires <suspends>
Any function that calls Sleep must be marked <suspends> (or called from one). OnBegin is already suspending; handler methods called via Subscribe are not — move long-running logic into a separate <suspends> task spawned with spawn{}.
6. Int ↔ Float conversion is explicit
Verse will not auto-convert. If your loop index Step is an int and you need it as a float for arithmetic, write (Step * 1.0) or cast explicitly — otherwise you'll get a type-mismatch compile error.