Reference Devices compiles

race_checkpoint_device: Building Lap-Tracked Race Courses

Want to build a sprint course, an obstacle gauntlet, or a vehicle lap track where players hit gates in order? The race_checkpoint_device is the gate. Paired with a race_manager_device it defines the route players must traverse — and in Verse you can react to every gate a player passes, reward them, and even reset their progress on the fly.

Updated Examples verified on the live UEFN compiler
Watch the Knotrace_checkpoint_device in ~90 seconds.

Overview

The race_checkpoint_device is a single gate in a larger racetrack. You place several of them along a route, hook them up to a race_manager_device, and the manager handles ordering — telling each runner which checkpoint is current (the one they need to reach next). Each checkpoint knows when it becomes the current target for a player, and when a player actually passes through it.

Reach for this device whenever you need ordered progress through space: a parkour course, a Rocket Racing-style lap track, a relay where every gate must be hit in sequence, or a scavenger trail. The Verse API lets you do far more than the manager alone — grant points the instant a player clears a gate, play a sound the first time anyone reaches it, disable a shortcut gate until a condition is met, or teleport a respawning player back to their last checkpoint with SetAsCurrentCheckpoint.

The three events give you a clean progress signal:

  • CheckpointBecomesCurrentForTheFirstTimeEvent — fires once, the very first time this gate becomes someone's target. Great for one-shot effects (lighting up a gate, opening a barrier).
  • CheckpointBecomesCurrentEvent — fires every time the gate becomes a player's current target. Use for per-player UI hints ("head this way!").
  • CheckpointCompletedEvent — fires when a player passes through. This is your reward / scoring hook.

And three methods to control it: Enable, Disable, and SetAsCurrentCheckpoint(Agent).

API Reference

race_checkpoint_device

Used in tandem with race_manager_device to define the route players must traverse.

Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).

race_checkpoint_device<public> := class<concrete><final>(creative_device_base):

Events (subscribe a handler to react):

Event Signature Description
CheckpointBecomesCurrentForTheFirstTimeEvent CheckpointBecomesCurrentForTheFirstTimeEvent<public>:listenable(agent) Signaled when this checkpoint becomes the next checkpoint that agents need to pass for the first time. Sends the first agent who is now targeting this checkpoint.
CheckpointBecomesCurrentEvent CheckpointBecomesCurrentEvent<public>:listenable(agent) Signaled when this checkpoint becomes the current checkpoint for agent. Sends the agent who is now targeting this checkpoint.
CheckpointCompletedEvent CheckpointCompletedEvent<public>:listenable(agent) Signaled when an agent passes this checkpoint. Sends the agent that passed this checkpoint.

Methods (call these to make the device act):

Method Signature Description
Enable Enable<public>():void Enables this device.
Disable Disable<public>():void Disables this device.
SetAsCurrentCheckpoint SetAsCurrentCheckpoint<public>(Agent:agent):void Sets this checkpoint as the current checkpoint for Agent. This only functions if Agent has not already passed this checkpoint.

Walkthrough

Let's build a three-gate sprint course. When a player passes a checkpoint we give them feedback via a HUD message; the first time a gate becomes active anywhere we trigger a one-time VFX burst to "light up" the gate; and when the player clears the final checkpoint we disable it so it can't be re-triggered.

Place three race_checkpoint_devices wired to a race_manager_device in your level, plus one vfx_spawner_device near the start gate, then drop this Verse device in and assign the references.

race_course_device := class(creative_device):

    # The first gate runners must reach.
    @editable
    StartGate : race_checkpoint_device = race_checkpoint_device{}

    # The middle gate.
    @editable
    MidGate : race_checkpoint_device = race_checkpoint_device{}

    # The final gate — the finish line.
    @editable
    FinishGate : race_checkpoint_device = race_checkpoint_device{}

    # A VFX burst to light up the first gate.
    @editable
    StartFx : vfx_spawner_device = vfx_spawner_device{}

    # Localized message helper — `message` params need a localized value, not a raw string.
    Hud<localizes>(S:string):message = "{S}"

    OnBegin<override>()<suspends>:void =
        # Light the start gate the FIRST time it becomes someone's target.
        StartGate.CheckpointBecomesCurrentForTheFirstTimeEvent.Subscribe(OnStartLitUp)

        # Per-player feedback whenever a gate becomes the current target.
        MidGate.CheckpointBecomesCurrentEvent.Subscribe(OnMidIsNext)

        # Score / react when a runner passes each gate.
        StartGate.CheckpointCompletedEvent.Subscribe(OnStartPassed)
        MidGate.CheckpointCompletedEvent.Subscribe(OnMidPassed)
        FinishGate.CheckpointCompletedEvent.Subscribe(OnFinished)

    # Fires ONCE — the first runner to target the start gate triggers the VFX.
    OnStartLitUp(Agent:agent):void =
        StartFx.Enable()
        StartFx.Restart()

    # Fires for each player when the mid gate becomes their next target.
    OnMidIsNext(Agent:agent):void =
        if (Player := player[Agent]):
            Print("A runner is now heading to the mid gate")

    OnStartPassed(Agent:agent):void =
        Print("Start gate cleared!")

    OnMidPassed(Agent:agent):void =
        Print("Mid gate cleared!")

    # The runner crossed the finish line — disable the gate so it stops reacting.
    OnFinished(Agent:agent):void =
        FinishGate.Disable()
        Print("Finish line reached — course complete!")

Line by line:

  • The four @editable fields let you assign your placed devices in the UEFN Details panel. Without @editable fields you cannot call a device's methods — a bare StartGate.Enable() on an unbound device fails.
  • Hud<localizes>(S:string):message is a helper that turns a plain string into the message type the HUD/UI APIs require. There is no StringToMessage built-in — you declare your own localizer like this.
  • In OnBegin we subscribe handlers to the events. Subscription happens once at startup; the handlers are plain methods at class scope.
  • CheckpointBecomesCurrentForTheFirstTimeEvent only ever fires once per device, so OnStartLitUp is the perfect place to enable and Restart() the VFX burst — it won't re-fire on later runners.
  • Each event hands us an agent. We unwrap it with player[Agent] when we need a player specifically (player[...] fails gracefully if the agent isn't a player).
  • OnFinished calls FinishGate.Disable() so the finish gate stops responding once cleared.

Common patterns

Reset a respawning player to their last checkpoint

When a player wipes out, send them back to a known gate by making it their current target again. SetAsCurrentCheckpoint only works if the agent hasn't already passed that checkpoint — so use it for backward resets within the route.

checkpoint_reset_device := class(creative_device):

    @editable
    RecoveryGate : race_checkpoint_device = race_checkpoint_device{}

    OnBegin<override>()<suspends>:void =
        # When a player reaches the recovery gate, remember it as their anchor.
        RecoveryGate.CheckpointCompletedEvent.Subscribe(OnReached)

    OnReached(Agent:agent):void =
        # Re-target this gate for the agent (e.g. after a fall) so the
        # manager routes them from here again.
        RecoveryGate.SetAsCurrentCheckpoint(Agent)

Enable a shortcut gate only after a condition

Keep a hidden shortcut checkpoint Disabled at start, then Enable it once the lead gate is cleared — opening an alternate route mid-race.

shortcut_gate_device := class(creative_device):

    @editable
    LeadGate : race_checkpoint_device = race_checkpoint_device{}

    @editable
    ShortcutGate : race_checkpoint_device = race_checkpoint_device{}

    OnBegin<override>()<suspends>:void =
        # Start with the shortcut closed.
        ShortcutGate.Disable()
        LeadGate.CheckpointCompletedEvent.Subscribe(OnLeadCleared)

    OnLeadCleared(Agent:agent):void =
        # Open the shortcut once any runner clears the lead gate.
        ShortcutGate.Enable()

Per-player navigation hint when a gate becomes current

CheckpointBecomesCurrentEvent fires every time the gate becomes a player's next target — ideal for telling that specific player where to go.

nav_hint_device := class(creative_device):

    @editable
    NextGate : race_checkpoint_device = race_checkpoint_device{}

    OnBegin<override>()<suspends>:void =
        NextGate.CheckpointBecomesCurrentEvent.Subscribe(OnBecameCurrent)

    OnBecameCurrent(Agent:agent):void =
        if (Player := player[Agent]):
            # This player should now head to NextGate.
            Print("Hint shown: head to the next gate")

Gotchas

  • You must declare the device as an @editable field. Calling RaceCheckpoint.Enable() on a device you never referenced inside your class(creative_device) produces an Unknown identifier error. Add the field, then assign the placed device in the Details panel.
  • SetAsCurrentCheckpoint is silently no-op once passed. The API only re-targets an agent to a checkpoint the agent hasn't already passed. You can't use it to skip a player forward past a gate they've completed — it's for backward resets (respawn recovery).
  • ...ForTheFirstTimeEvent fires exactly once for the whole device, not once per player. If you want per-player reactions, subscribe to CheckpointBecomesCurrentEvent instead.
  • Events hand you a raw agent, not a player. If you need player-specific data, unwrap with if (Player := player[Agent]):. Skipping the unwrap and treating the agent as a player will fail to compile.
  • message params need a localized value. Don't pass a bare "text" to UI/HUD APIs — declare a <localizes> helper like Hud<localizes>(S:string):message = "{S}" and call Hud("..."). There is no StringToMessage.
  • Race checkpoints rely on a race_manager_device for ordering. The checkpoint device defines a gate, but the manager decides sequence and laps. Wire them together in the editor — Verse controls behavior, not the route topology.
  • Restart() on the VFX spawner only re-triggers burst-type effects. For looping effects, Enable/Disable is what toggles them.

Guides & scripts that use race_checkpoint_device

Step-by-step tutorials that put this object to work.

Build your own lesson with race_checkpoint_device

Generate a personalized, step-by-step lesson plan built around this object — grounded in this exact reference and our compile-verified knowledge base.

Build a lesson →