Every racer on Barnaby's rally route is really just a point in space — three numbers, updated every frame. Learn to read that point and compare it against the points you care about (a finish-line arch, a checkpoint marker), and suddenly you can answer the questions every race asks: did they finish? and where should they go next? This lesson is pure jungle-grade vector craft: GetTransform().Translation to read a position, Distance() to measure between two of them.
What you will build
The finish-line proximity check and nearest-checkpoint helper for Barnaby's Jungle Mod-Rally — the exact piece the capstone uses to detect the winner at Sunrise Summit. One device that:
- reads the finish-line prop's world position once,
- polls every racer's position on a half-second heartbeat,
- calls the finish when someone gets within
FinishRadiuscentimetres, and - answers "which checkpoint is nearest to me?" at the press of a button.
Distances in UEFN are measured in centimetres, so 500.0 means five metres. Keep that conversion taped to your monitor; it is the number-one source of "my trigger radius is the size of a coconut" bugs.
Walkthrough
Reading a position
Everything positional in Verse — a fort_character, a creative_prop, a device — carries a transform, and the part we want is its Translation: a vector3 holding world-space X, Y, Z:
Where := Body.GetTransform().Translation # a vector3: Where.X, Where.Y, Where.Z
To get a racer's Body you walk the chain you met in the find-the-player lesson: GetPlayspace() → GetPlayers() → P.GetFortCharacter[] (failable — a mid-respawn racer has no body, and the if just skips them).
Measuring between two positions
/UnrealEngine.com/Temporary/SpatialMath gives you the whole measuring kit:
Distance(V1, V2)— straight-line distance between twovector3values, in cm.DistanceXY(V1, V2)— the same but ignoring height. Perfect for a finish line, where a jumping racer should still count.DistanceSquared(V1, V2)— the distance before the square root. Cheaper, and fine when you only need to compare.
The full device
Drop a prop where your finish arch stands, scatter a few checkpoint marker props, add a button, and wire them all into this device:
using { /Fortnite.com/Devices }
using { /Fortnite.com/Characters }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Watches every racer's position, calls the finish, and answers
# "which checkpoint is nearest?" on demand.
finish_line_device := class(creative_device):
# The prop that marks the finish-line arch at Sunrise Summit.
@editable
FinishLine : creative_prop = creative_prop{}
# Checkpoint marker props along the rally route, wired in course order.
@editable
Checkpoints : []creative_prop = array{}
# Press this for a "which checkpoint is nearest?" hint.
@editable
HintButton : button_device = button_device{}
# How close (in centimetres) counts as crossing. 500.0 = 5 metres.
@editable
FinishRadius : float = 500.0
OnBegin<override>()<suspends> : void =
HintButton.InteractedWithEvent.Subscribe(OnHintRequested)
# Cache the finish position once -- the arch does not move.
FinishPos := FinishLine.GetTransform().Translation
Print("Finish line is at X={FinishPos.X} Y={FinishPos.Y} Z={FinishPos.Z}")
var RaceOver : logic = false
loop:
Sleep(0.5)
if (RaceOver?):
break
for (P : GetPlayspace().GetPlayers()):
if (Body := P.GetFortCharacter[]):
RacerPos := Body.GetTransform().Translation
D := Distance(RacerPos, FinishPos)
if (D <= FinishRadius):
Print("A racer reached the finish, {D} cm from the marker!")
set RaceOver = true
# Button handler: tell the presser which checkpoint is closest to them.
OnHintRequested(Presser : agent) : void =
if (Body := Presser.GetFortCharacter[]):
RacerPos := Body.GetTransform().Translation
if (Index := NearestCheckpointIndex(RacerPos)?):
Print("Nearest checkpoint is number {Index} on the route")
# Index of the checkpoint closest to Pos; empty when none are wired up.
NearestCheckpointIndex(Pos : vector3)<transacts> : ?int =
var Best : ?int = false
var BestDist : float = 999999999.0
for (Index -> Checkpoint : Checkpoints):
D := Distance(Checkpoint.GetTransform().Translation, Pos)
if (D < BestDist):
set BestDist = D
set Best = option{Index}
Best
How it works, top to bottom:
FinishPos := FinishLine.GetTransform().Translation— read the arch's position once, before the loop. It never moves, so there is no reason to re-ask fifty times a minute.- The heartbeat
loop+Sleep(0.5)— position checks do not need to run every frame. Twice a second is plenty for a finish line and costs almost nothing. P.GetFortCharacter[]— the failable bridge fromplayerto their body. No body (mid-respawn, just joined) means the racer is skipped this tick, exactly as it should be.Distance(RacerPos, FinishPos) <= FinishRadius— the proximity check itself. One function call, one comparison.set RaceOver = true+break— first racer inside the radius ends the watch. The capstone replaces thePrintwith the podium sequence.NearestCheckpointIndex— the classic find-the-minimum sweep: startBestDistabsurdly high, walkCheckpointswithIndex -> Checkpoint, and keep whichever marker measures shortest. It returns?int(an optional, from the optionals lesson) so an unwired checkpoint array fails gracefully instead of lying with a fake index.
Common patterns
Flat-ground check with DistanceXY
# Racers love to hit the line mid-jump. DistanceXY ignores height,
# so a racer 3 metres in the AIR above the marker still counts.
CheckFinishFlat(RacerPos : vector3, FinishPos : vector3, Radius : float) : void =
FlatD := DistanceXY(RacerPos, FinishPos)
if (FlatD <= Radius):
Print("Crossed the line (flat distance {FlatD} cm)")
Compare racers without the square root
# "Who is closer?" does not need the actual distance -- comparing
# SQUARED distances gives the same winner and skips the square root.
CallTheLeader(PosA : vector3, PosB : vector3, FinishPos : vector3) : void =
if (DistanceSquared(PosA, FinishPos) < DistanceSquared(PosB, FinishPos)):
Print("Racer A leads!")
else:
Print("Racer B leads!")
Square roots are not expensive enough to fear, but when a check runs for every racer, every tick, skipping work you never needed is just good jungle hygiene.
Where this goes next
This is piece 16 of Barnaby's Jungle Mod-Rally, the north-jungle capstone. The rally imports this lesson directly: the finish gate at Sunrise Summit is exactly this Distance()-versus-radius check, and the nearest-checkpoint sweep becomes the helper that respawning riders use to rejoin the route. Pair it with the filter-an-array lesson's still_racing list and the trigger-device checkpoint sensors, and you have the whole spine of race-position logic. The distance helper itself graduates into the shared CodewoodKit module (the creating-custom-modules lesson) so east-volcano and the-deeps can measure things too — write it once, race with it everywhere.