Reference Devices compiles

player_movement_settings_device: Custom Movement Rules for Every Player

The `player_movement_settings_device` lets you override how players move — think sprint speed, jump height, gravity, or air control — and apply those overrides to one player or everyone at once. It uses a priority stack so multiple devices can coexist without fighting each other: the highest-priority active device wins. Reach for it whenever your game needs movement that changes mid-match: a speed boost zone, a low-gravity arena, a slow-motion finale, or a parkour course with slippery floors.

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

Overview

The player_movement_settings_device is a Creative device you configure entirely inside the UEFN editor (walk speed, jump count, gravity scale, etc.) and then control at runtime through Verse. Your Verse code doesn't set individual floats — it applies or removes a pre-configured device to/from specific agents.

Key design points:

  • Priority stack — every player_movement_settings_device has a numeric priority set in the editor. When multiple devices are applied to the same player, the one with the highest priority is active. Ties go to the most recently applied device.
  • Per-agent or globalAddTo(Agent) / RemoveFrom(Agent) target one player; AddToAll() / RemoveFromAll() hit everyone currently in the scene.
  • Query helpersGetPriority() returns the device's configured priority so you can reason about stacking order; GetRegisteredAgents() returns everyone currently registered to that device.

Typical use-cases: speed-boost pads, slow-motion zones, zero-gravity rooms, parkour courses with special movement rules, end-game power-up phases.

API Reference

player_movement_settings_device

Used to update the player character's movement settings on different movement mode.

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

player_movement_settings_device<public> := class<concrete><final>(creative_device_base, enableable):

Methods (call these to make the device act):

Method Signature Description
AddTo AddTo<public>(Agent:agent):void Adds the movement settings to the provided agent, activating if it is in the highest priority. * The highest priority device is applied to players and test players. Ties are broken by which is applied most recently. * Fails if the provided
AddToAll AddToAll<public>():void Adds the movement settings to all the agents in the scene, activating if it is in the highest priority. * The highest priority device is applied to players and test players. Ties are broken by which is applied most recently.
RemoveFrom RemoveFrom<public>(Agent:agent):void Removes the movement settings from the provided agent. Fails if the provided agent doesn't have the movement settings applied.
RemoveFromAll RemoveFromAll<public>():void Removes the movement settings from all the active agents.
GetPriority GetPriority<public>()<reads>:float Returns the priority of the device, the active device in the highest priority will be applied to the provided agents.
GetRegisteredAgents GetRegisteredAgents<public>()<reads>:[]agent Returns the player agents registered to this device.

Walkthrough

Scenario: A parkour island has two zones. Zone A is a speed boost corridor — players who enter get fast movement settings applied. Zone B is a low-gravity vault room — players who enter get low-gravity movement settings. When a player leaves either zone, their special settings are removed. A third device with the lowest priority acts as the global baseline applied to everyone at game start.

This single Verse device wires up three player_movement_settings_device references and two trigger_device references (entry/exit triggers per zone) to drive the whole system.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

# ─────────────────────────────────────────────────────────────────
# movement_zone_manager_device
# Wire up in the UEFN Details panel:
#   BaselineSettings   → a player_movement_settings_device (priority 1, default walk speed)
#   SpeedBoostSettings → a player_movement_settings_device (priority 10, high walk speed)
#   LowGravSettings    → a player_movement_settings_device (priority 10, low gravity)
#   SpeedZoneEnter     → trigger_device covering the entry of Zone A
#   SpeedZoneExit      → trigger_device covering the exit of Zone A
#   GravZoneEnter      → trigger_device covering the entry of Zone B
#   GravZoneExit       → trigger_device covering the exit of Zone B
# ─────────────────────────────────────────────────────────────────
movement_zone_manager_device := class(creative_device):

    # ── editable device references ──────────────────────────────
    @editable BaselineSettings   : player_movement_settings_device = player_movement_settings_device{}
    @editable SpeedBoostSettings : player_movement_settings_device = player_movement_settings_device{}
    @editable LowGravSettings    : player_movement_settings_device = player_movement_settings_device{}

    @editable SpeedZoneEnter : trigger_device = trigger_device{}
    @editable SpeedZoneExit  : trigger_device = trigger_device{}
    @editable GravZoneEnter  : trigger_device = trigger_device{}
    @editable GravZoneExit   : trigger_device = trigger_device{}

    # ── lifecycle ───────────────────────────────────────────────
    OnBegin<override>()<suspends>:void =
        # Apply the baseline movement settings to every player at game start.
        # Priority 1 means any zone device (priority 10) will override it.
        BaselineSettings.AddToAll()

        # Log the baseline priority so designers can verify stacking order.
        Print("Baseline movement priority: {BaselineSettings.GetPriority()}")
        Print("SpeedBoost priority:        {SpeedBoostSettings.GetPriority()}")
        Print("LowGrav priority:           {LowGravSettings.GetPriority()}")

        # Subscribe zone triggers to their handlers.
        SpeedZoneEnter.TriggeredEvent.Subscribe(OnEnterSpeedZone)
        SpeedZoneExit.TriggeredEvent.Subscribe(OnExitSpeedZone)
        GravZoneEnter.TriggeredEvent.Subscribe(OnEnterGravZone)
        GravZoneExit.TriggeredEvent.Subscribe(OnExitGravZone)

    # ── speed zone handlers ─────────────────────────────────────
    # trigger_device.TriggeredEvent sends ?agent, so we unwrap it.
    OnEnterSpeedZone(MaybeAgent : ?agent):void =
        if (Agent := MaybeAgent?):
            # Stack the speed-boost device on top of the baseline.
            SpeedBoostSettings.AddTo(Agent)
            Print("Speed boost applied. Registered agents: {SpeedBoostSettings.GetRegisteredAgents().Length}")

    OnExitSpeedZone(MaybeAgent : ?agent):void =
        if (Agent := MaybeAgent?):
            # Remove only the speed-boost layer; baseline remains active.
            SpeedBoostSettings.RemoveFrom(Agent)

    # ── low-gravity zone handlers ────────────────────────────────
    OnEnterGravZone(MaybeAgent : ?agent):void =
        if (Agent := MaybeAgent?):
            LowGravSettings.AddTo(Agent)

    OnExitGravZone(MaybeAgent : ?agent):void =
        if (Agent := MaybeAgent?):
            LowGravSettings.RemoveFrom(Agent)

Line-by-line explanation

Lines What's happening
@editable fields Expose all three movement devices and all four triggers to the UEFN Details panel so designers can wire them up without touching code.
BaselineSettings.AddToAll() Pushes the baseline movement profile onto every player the moment the round starts. Because its priority is 1, any zone device (priority 10) will override it.
GetPriority() calls Read-only query — useful for debug logging or runtime assertions that your stack order is correct.
Subscribe(OnEnterSpeedZone) Registers a class-scope method as the event handler. The method signature must match (?agent):void.
if (Agent := MaybeAgent?) Unwraps the optional agent. If no agent triggered the event (e.g. a scripted trigger), the block is skipped safely.
SpeedBoostSettings.AddTo(Agent) Layers the speed-boost profile on top of the baseline for that specific player only.
SpeedBoostSettings.RemoveFrom(Agent) Pops the speed-boost layer; the baseline (still registered) immediately becomes active again.
GetRegisteredAgents().Length Queries how many players currently have the speed-boost device registered — handy for analytics or UI.

Common patterns

Pattern 1 — Global slow-motion finale (AddToAll / RemoveFromAll)

At the end of a match, apply a dramatic slow-movement device to every surviving player, then remove it after the victory fanfare.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

finale_slowmo_device := class(creative_device):

    @editable SlowMoSettings : player_movement_settings_device = player_movement_settings_device{}
    @editable EndGameDevice  : end_game_device = end_game_device{}

    OnBegin<override>()<suspends>:void =
        EndGameDevice.GameOverEvent.Subscribe(OnGameOver)

    OnGameOver(MaybeAgent : ?agent):void =
        # Apply slow movement to EVERY player simultaneously for the cinematic moment.
        SlowMoSettings.AddToAll()
        # After 5 seconds, restore normal movement for all players.
        Sleep(5.0)
        SlowMoSettings.RemoveFromAll()

Pattern 2 — Inspect the priority stack before applying

Before layering a new movement device, check whether it actually outranks what's already applied. This is useful when you have many competing zone devices and want to avoid silent no-ops.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

priority_guard_device := class(creative_device):

    @editable HighTierMovement : player_movement_settings_device = player_movement_settings_device{}
    @editable LowTierMovement  : player_movement_settings_device = player_movement_settings_device{}
    @editable ActivateTrigger  : trigger_device = trigger_device{}

    OnBegin<override>()<suspends>:void =
        # Apply the low-tier baseline to everyone.
        LowTierMovement.AddToAll()

        # Verify the high-tier device actually outranks the low-tier one.
        HighPri := HighTierMovement.GetPriority()
        LowPri  := LowTierMovement.GetPriority()
        if (HighPri > LowPri):
            Print("Stack order confirmed: high-tier will override low-tier.")
        else:
            Print("WARNING: high-tier priority ({HighPri}) does not exceed low-tier ({LowPri}). Check device settings!")

        ActivateTrigger.TriggeredEvent.Subscribe(OnActivate)

    OnActivate(MaybeAgent : ?agent):void =
        if (Agent := MaybeAgent?):
            HighTierMovement.AddTo(Agent)

Pattern 3 — Audit registered agents before removal

Before calling RemoveFrom, confirm the agent is actually registered to avoid a runtime failure (the method fails if the agent isn't registered).

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

audit_removal_device := class(creative_device):

    @editable BoostSettings  : player_movement_settings_device = player_movement_settings_device{}
    @editable GrantTrigger   : trigger_device = trigger_device{}
    @editable RevokeTrigger  : trigger_device = trigger_device{}

    OnBegin<override>()<suspends>:void =
        GrantTrigger.TriggeredEvent.Subscribe(OnGrant)
        RevokeTrigger.TriggeredEvent.Subscribe(OnRevoke)

    OnGrant(MaybeAgent : ?agent):void =
        if (Agent := MaybeAgent?):
            BoostSettings.AddTo(Agent)

    OnRevoke(MaybeAgent : ?agent):void =
        if (Agent := MaybeAgent?):
            # GetRegisteredAgents() returns the current list — iterate to check membership.
            Registered := BoostSettings.GetRegisteredAgents()
            for (Reg : Registered):
                if (Reg = Agent):
                    # Safe to remove: we confirmed the agent is registered.
                    BoostSettings.RemoveFrom(Agent)

Gotchas

1. RemoveFrom fails if the agent isn't registered

RemoveFrom is a failable operation — calling it on an agent who was never added (or was already removed) causes a runtime failure. Always guard with GetRegisteredAgents() if you're not certain, as shown in Pattern 3 above.

2. Priority ties go to the most recently applied device

If two devices share the same priority number and both are applied to the same player, the last one applied wins. This can cause subtle bugs when AddToAll() is called in rapid succession from different devices. Give each device a unique priority in the editor to avoid this.

3. AddToAll only covers agents present at call time

AddToAll() applies to every agent currently in the scene when the call is made. Players who join later are NOT automatically registered. If your island supports late-joining, subscribe to a player-joined event and call AddTo(Agent) for each new arrival.

4. The device must be enabled to take effect

player_movement_settings_device inherits from enableable. If the device is disabled in the editor or via Disable(), AddTo / AddToAll will still register agents, but the settings won't activate. Call Enable() first if you're toggling devices on and off.

5. Settings are configured in the editor, not in Verse

You cannot set individual movement values (walk speed, jump height, etc.) from Verse code. All tuning happens in the device's Details panel in UEFN. Verse only controls which agents the device is applied to and when. If you need different movement profiles, place multiple player_movement_settings_device instances with different editor settings and reference each one as a separate @editable field.

6. GetPriority() is read-only

The <reads> effect on GetPriority() means it cannot be called inside a context that forbids reads (rare in practice), and you cannot use it to set the priority at runtime — priority is baked in the editor.

Guides & scripts that use player_movement_settings_device

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

Build your own lesson with player_movement_settings_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 →