Overview
A vector3 is a 3-dimensional vector with three float components — X, Y, and Z. In UEFN it is the universal language of place: where a prop sits, which direction a cannon points, how far a player is from the dock. Nearly every spatial API in Verse either hands you a vector3 or asks for one.
On a bright cel-shaded cove you'll reach for vector3 whenever you want to:
- Teleport a pirate onto the ship's deck.
- Measure distance between a player and the buried chest, so a hint plays only when they're close.
- Move a prop — a raft drifting toward shore — by interpolating between two positions.
The struct is <persistable>, so a saved position survives across sessions, and <comparable>, so two positions can be checked for equality. It ships in the SpatialMath module — that's why every example below imports /UnrealEngine.com/Temporary/SpatialMath.
API Reference
vector3
3-dimensional vector with
floatcomponents.
Full public surface, resolved verbatim from the live Epic digest (Verse.digest.verse).
vector3<native><public> := struct<concrete><computes><persistable><uht_comparable>:
player
Full public surface, resolved verbatim from the live Epic digest (Verse.digest.verse). Inherited members are merged from agent.
player<native><public> := class<unique><persistent><module_scoped_var_weak_map_key><epic_internal>(agent):
Walkthrough
Let's build a "Beach the Raft" moment. When a player steps on a trigger at the end of the dock, we read the player's world position, compute a target vector3 a few meters out over the lagoon, and glide the raft prop there. We also measure the raft's start distance so we can log how far it traveled.
using { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Verse }
# Beaches a raft prop toward the player who steps on the dock trigger.
beach_the_raft := class(creative_device):
# Placed devices/props MUST be @editable fields to be callable.
@editable
DockTrigger : trigger_device = trigger_device{}
@editable
Raft : creative_prop = creative_prop{}
OnBegin<override>()<suspends> : void =
# Subscribe the handler in OnBegin.
DockTrigger.TriggeredEvent.Subscribe(OnDockStepped)
# Event handler is a METHOD at class scope.
OnDockStepped(Agent : ?agent) : void =
# A triggered event hands us an optional agent — unwrap it.
if (Player := Agent?):
# Where does the raft start? GetTransform().Translation is a vector3.
StartPos : vector3 = Raft.GetTransform().Translation
# Build a target position: 500 units up the Y axis, out over the lagoon.
TargetPos : vector3 = vector3:
X := StartPos.X
Y := StartPos.Y + 500.0
Z := StartPos.Z
# Measure how far the raft will travel (component math on floats).
DX := TargetPos.X - StartPos.X
DY := TargetPos.Y - StartPos.Y
DZ := TargetPos.Z - StartPos.Z
DistanceSq := DX * DX + DY * DY + DZ * DZ
# Glide the raft to the new vector3 over 3 seconds.
if (DistanceSq > 0.0):
spawn { GlideRaft(TargetPos) }
GlideRaft(Target : vector3)<suspends> : void =
# MoveTo takes a target vector3, a rotation, and a duration.
Move := Raft.MoveTo(Target, Raft.GetTransform().Rotation, 3.0)
Line by line:
@editable DockTrigger/Raft— you can only call a placed device or prop through an@editablefield; a bareRaft.MoveTo(...)fails with Unknown identifier.DockTrigger.TriggeredEvent.Subscribe(OnDockStepped)— wire the step event to our method, done once inOnBegin.Agent : ?agentthenif (Player := Agent?)— the trigger hands us an optional agent; we must unwrap it before use.Raft.GetTransform().Translation— atransform'sTranslationfield IS avector3. That's our starting point.- The
vector3:block constructs a brand-new position, reusing X and Z but pushing Y outward. - The
DX/DY/DZlines are plain float arithmetic (Verse never auto-converts int↔float, so we write500.0, not500). Raft.MoveTo(Target, ...)consumes ourvector3to actually slide the prop across the water.
Common patterns
Measure distance from the chest before granting a hint
Read two positions and compare — here we only fire a haptic-ish reaction when the player is within range of the treasure.
using { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
chest_proximity := class(creative_device):
@editable
CheckTrigger : trigger_device = trigger_device{}
@editable
Chest : creative_prop = creative_prop{}
@editable
HintBeacon : trigger_device = trigger_device{}
OnBegin<override>()<suspends> : void =
CheckTrigger.TriggeredEvent.Subscribe(OnChecked)
OnChecked(Agent : ?agent) : void =
if (Player := Agent?, Char := Player.GetFortCharacter[]):
PlayerPos : vector3 = Char.GetTransform().Translation
ChestPos : vector3 = Chest.GetTransform().Translation
DX := PlayerPos.X - ChestPos.X
DY := PlayerPos.Y - ChestPos.Y
DZ := PlayerPos.Z - ChestPos.Z
DistSq := DX * DX + DY * DY + DZ * DZ
# Within ~10 metres? 1000 units squared = 1,000,000.
if (DistSq < 1000000.0):
HintBeacon.Trigger(Player)
Lerp a spotlight glow along a value between two positions' heights
Lerp blends two floats. Here we ease a lantern prop's Z height from the deck up to the crow's nest so it "rises" over the pirate ship.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Verse }
rising_lantern := class(creative_device):
@editable
Lantern : creative_prop = creative_prop{}
OnBegin<override>()<suspends> : void =
Base : vector3 = Lantern.GetTransform().Translation
LowZ := Base.Z
HighZ := Base.Z + 800.0
# Ease upward across 10 steps.
var Step : int = 0
loop:
if (Step > 10):
break
T := Step * 1.0 / 10.0
NewZ := Lerp(LowZ, HighZ, T)
Target : vector3 = vector3{X := Base.X, Y := Base.Y, Z := NewZ}
Rise := Lantern.MoveTo(Target, Lantern.GetTransform().Rotation, 0.4)
set Step = Step + 1
Store a spawn point as a persistable vector3
vector3 is <persistable>, so a saved location can back a checkpoint. Here we stash a docked player's position when they hit a button.
using { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
checkpoint_saver := class(creative_device):
@editable
SaveButton : button_device = button_device{}
# A vector3 can be held in a var and reused later.
var LastCheckpoint : vector3 = vector3{X := 0.0, Y := 0.0, Z := 0.0}
OnBegin<override>()<suspends> : void =
SaveButton.InteractedWithEvent.Subscribe(OnSave)
OnSave(Agent : agent) : void =
if (Player := player[Agent], Char := Player.GetFortCharacter[]):
set LastCheckpoint = Char.GetTransform().Translation
Gotchas
vector3lives in two modules. The one you almost always want in device Verse is/UnrealEngine.com/Temporary/SpatialMath(X/Y/Z floats), whichGetTransform().TranslationandMoveTouse. There's also a/Verse.org/SpatialMathvariant; useFromVector3(...)to convert between them if an API demands the other flavour.- No int↔float auto-conversion. Every component is a
float. Write500.0, not500. Dividing an int step by 10 needsStep * 1.0 / 10.0(or a float variable) to stay a float. - Distance math is manual.
vector3itself exposes no methods — subtract components and sum the squares yourself, or lean on SpatialMath helpers likeDistance(which is forrotation, not positions). Comparing squared distances avoids a square-root and is perfectly fine for range checks. TranslationvsScale. AtransformhasTranslation(a positionvector3),Rotation, andScale(also avector3, but of multipliers). Don't feed a Scale vector intoMoveToexpecting a location.- Unwrap the optional agent. Trigger events give
(Agent : ?agent); alwaysif (P := Agent?):before reading a character's position, or the code won't compile. - Constructing with a block vs braces. Both
vector3{X := 1.0, Y := 2.0, Z := 3.0}and the indentedvector3:block work; omitted components default to0.0.