Overview
Default parameters are a core Verse language feature — not a device — that make your functions flexible without exploding into a dozen near-identical versions. You declare a parameter with a leading ? (a named parameter) and give it an = value fallback. Callers can then omit that argument and get the default, or pass it explicitly by name (?Points := 5).
This matters the moment your island grows. Imagine a sunny cove with a score_manager_device that awards points. Most pickups give 1 point, but the golden chest on the clifftop gives 10, and a hidden tide-pool gem gives 3. Without defaults you'd write three functions or pass every argument every time. With defaults you write one AwardLoot helper: call AwardLoot(Player) for the common case, AwardLoot(Player, ?Bonus := 10) for the chest.
Key rules from the Verse language:
- Named parameters use a leading
?in the declaration:MyFunc(?Points:int = 1). - A default value can even reference an earlier parameter:
CreateRange(?Start:int, ?End:int = Start + 10). - Defaults can reference class fields, and subclasses can
<override>those fields to change the default. - Verse does not auto-convert
inttofloat, so a default typedfloatmust be written1.0, not1.
Reach for default parameters whenever you have a function that is usually called the same way but occasionally needs a tweak.
API Reference
(API surface could not be resolved for this device.)
Walkthrough
Here's the cove scene: three trigger plates on the dock. Stepping on any plate awards score through a single shared score_manager_device. The common plate gives the default 1 point; the chest plate passes a bonus; the gem plate passes a named ?Points. All three call the same AwardLoot method thanks to default parameters.
The score_manager_device's Activate(Agent:agent) grants the currently configured score, and Increment(Agent:agent) bumps the next award by 1. We use Increment in a loop to raise the total, then Activate to grant it — all driven by our defaulted parameter.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/UI }
cove_loot_device := class(creative_device):
# The shared score device that grants points on the cove.
@editable
Scorer : score_manager_device = score_manager_device{}
# Common beach-loot plate: awards the default amount.
@editable
CommonPlate : trigger_device = trigger_device{}
# Clifftop golden chest: awards a big bonus.
@editable
ChestPlate : trigger_device = trigger_device{}
# Tide-pool gem: awards a small named amount.
@editable
GemPlate : trigger_device = trigger_device{}
# ONE function, called three ways. ?Points defaults to 1.
AwardLoot(Player : agent, ?Points : int = 1) : void =
# Bring the score device up to Points by incrementing.
# (First Activate grants 1, so we Increment Points-1 extra times.)
var Remaining : int = Points
loop:
if (Remaining <= 1):
break
Scorer.Increment(Player)
set Remaining -= 1
Scorer.Activate(Player)
OnCommonStepped(Agent : ?agent) : void =
if (Player := Agent?):
AwardLoot(Player) # uses default 1
OnChestStepped(Agent : ?agent) : void =
if (Player := Agent?):
AwardLoot(Player, ?Points := 10) # named override
OnGemStepped(Agent : ?agent) : void =
if (Player := Agent?):
AwardLoot(Player, ?Points := 3) # named override
OnBegin<override>()<suspends> : void =
CommonPlate.TriggeredEvent.Subscribe(OnCommonStepped)
ChestPlate.TriggeredEvent.Subscribe(OnChestStepped)
GemPlate.TriggeredEvent.Subscribe(OnGemStepped)
Line by line:
- The
@editablefields let you drop the score device and three trigger plates into your level and wire them in the Details panel. AwardLoot(Player : agent, ?Points : int = 1)— the star of the show.?Pointsis a named parameter with a default of1. Any caller who omits it gets 1.- Inside, we loop calling
Scorer.Increment(Player)to raise the pending award, thenScorer.Activate(Player)to grant it to that agent.IncrementandActivateare realscore_manager_devicemethods withagentoverloads. - Each
On...Steppedhandler receives(Agent : ?agent)from theTriggeredEvent. We unwrap it withif (Player := Agent?):before use. OnCommonSteppedcallsAwardLoot(Player)— no?Points, so the default1applies.OnChestSteppedandOnGemSteppedpass?Points := 10and?Points := 3by name. Same function, three behaviors.OnBeginsubscribes every plate to its handler. This is where all wiring happens.
Common patterns
1. A default that references an earlier parameter
Default values can be computed from parameters declared before them. Here a player_reference_device registers a player, and a helper decides how many bonus points to grant based on a Base amount — with ?Bonus defaulting to Base * 2.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
range_bonus_device := class(creative_device):
@editable
Scorer : score_manager_device = score_manager_device{}
@editable
Reference : player_reference_device = player_reference_device{}
@editable
StartPlate : trigger_device = trigger_device{}
# ?Bonus defaults to Base * 2 — a later default using an earlier param.
GrantScaled(Player : agent, Base : int, ?Bonus : int = Base * 2) : void =
Reference.Register(Player)
var Total : int = Base + Bonus
loop:
if (Total <= 1):
break
Scorer.Increment(Player)
set Total -= 1
Scorer.Activate(Player)
OnStepped(Agent : ?agent) : void =
if (Player := Agent?):
# Base 5, Bonus defaults to 10 -> total 15.
GrantScaled(Player, 5)
OnBegin<override>()<suspends> : void =
StartPlate.TriggeredEvent.Subscribe(OnStepped)
2. Toggling a device with a defaulted flag
A single helper enables or disables the score device. ?On defaults to true, so the common "turn it on" call is short, while a shutdown call passes ?On := false.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
toggle_scorer_device := class(creative_device):
@editable
Scorer : score_manager_device = score_manager_device{}
@editable
OpenGate : trigger_device = trigger_device{}
@editable
CloseGate : trigger_device = trigger_device{}
# ?On defaults to true: SetScoring(Player) enables, SetScoring(Player, ?On := false) disables.
SetScoring(Player : agent, ?On : logic = true) : void =
if (On?):
Scorer.Enable(Player)
else:
Scorer.Disable(Player)
OnOpen(Agent : ?agent) : void =
if (Player := Agent?):
SetScoring(Player) # default true -> Enable
OnClose(Agent : ?agent) : void =
if (Player := Agent?):
SetScoring(Player, ?On := false) # -> Disable
OnBegin<override>()<suspends> : void =
OpenGate.TriggeredEvent.Subscribe(OnOpen)
CloseGate.TriggeredEvent.Subscribe(OnClose)
3. A class-field default overridden by a subclass
Defaults can pull from a class field, and a subclass can <override> that field to change the default behavior — clifftop "hard mode" awards more per pickup.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
cove_rules_device := class(creative_device):
@editable
Scorer : score_manager_device = score_manager_device{}
@editable
Plate : trigger_device = trigger_device{}
# Field used as the default award amount.
DefaultAward : int = 1
Award(Player : agent, ?Points : int = DefaultAward) : void =
var Left : int = Points
loop:
if (Left <= 1):
break
Scorer.Increment(Player)
set Left -= 1
Scorer.Activate(Player)
OnStepped(Agent : ?agent) : void =
if (Player := Agent?):
Award(Player) # uses DefaultAward
OnBegin<override>()<suspends> : void =
Plate.TriggeredEvent.Subscribe(OnStepped)
Gotchas
- The
?is required, in both places. Default parameters are named parameters — declare them with a leading?(?Points : int = 1) and pass them with the same?(AwardLoot(Player, ?Points := 10)). Forgetting the?on the call gives an 'Unknown identifier' or argument-count error. - No int↔float auto-convert in defaults. If a parameter is
float, its default must be written with a decimal:?Speed : float = 1.0, never= 1. Mixing types won't compile. - Order matters for referencing earlier params.
?End : int = Start + 10only works becauseStartis declared beforeEnd. You can't reference a parameter that comes later. - Named-parameter call syntax uses
:=, not=. Inside a call you write?Points := 10(assignment-style), matching Verse's named-argument syntax. - Unwrap the event agent first.
TriggeredEventhandlers receive(Agent : ?agent). Always doif (Player := Agent?):before passing it to a function likeScorer.Activate(Player)— the option must be opened. - Defaults live with the function, not the device. Default parameters are a language feature; the
score_manager_deviceandplayer_reference_devicemethods themselves have fixed signatures. Your defaults only affect your helper functions that wrap those calls.