Overview
The grind_rail_device is a placeable Creative device that creates a rideable rail players can grind along. Out of the box it's a static prop, but through Verse you unlock its full potential:
- React to riders —
StartedGrindingEventandEndedGrindingEventfire whenever a player hops on or off, letting you trigger score grants, sound cues, or state changes. - Control availability —
EnableandDisablelet you gate rails behind game conditions (e.g., only activate a rail after a key is collected). - Visual feedback —
SetRailColorchanges the rail's glow color at runtime;HideandShowtoggle visibility without affecting grindability.
Reach for grind_rail_device any time you want rails that are more than decoration — scoring systems, timed challenges, puzzle gates, or dynamic arenas all benefit from its event-driven API.
API Reference
grind_rail_device
Used to create customizable Grind Rails.
Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse).
grind_rail_device<public> := class<concrete><final>(creative_device_base):
Events (subscribe a handler to react):
| Event | Signature | Description |
|---|---|---|
StartedGrindingEvent |
StartedGrindingEvent<public>:listenable(agent) |
Signaled when an agent starts grinding on this grind_rail_device. |
EndedGrindingEvent |
EndedGrindingEvent<public>:listenable(agent) |
Signaled when an agent starts grinding on this grind_rail_device. |
Methods (call these to make the device act):
| Method | Signature | Description |
|---|---|---|
Enable |
Enable<public>():void |
Enables this device, letting players grind on the rail. |
Disable |
Disable<public>():void |
Disables this device, preventing players from grinding on the rail. |
SetRailColor |
SetRailColor<public>(Color:color):void |
Sets the color of the Grind Rail. |
Hide |
Hide<public>():void |
Hides the track. Players can still grind on the track if it is enabled. |
Show |
Show<public>():void |
Make this track visible. |
Walkthrough
Scenario: A skate-park mini-game with three rails. Each rail is color-coded: blue when idle, gold while a player is grinding it. When a player finishes grinding, they earn a score tick and the rail flashes back to blue. A manager device subscribes to all three rails and tracks total grinds per player.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Fortnite.com/Characters }
using { /Verse.org/Colors }
# Attach this creative_device to a Verse Device actor in UEFN.
# Wire up Rail1, Rail2, Rail3, and ScoreManager in the Details panel.
grind_park_manager := class(creative_device):
# Three grind rails placed in the level — wire these in the Details panel.
@editable
Rail1 : grind_rail_device = grind_rail_device{}
@editable
Rail2 : grind_rail_device = grind_rail_device{}
@editable
Rail3 : grind_rail_device = grind_rail_device{}
# A score manager device to grant points (wire in Details panel).
@editable
ScoreManager : score_manager_device = score_manager_device{}
# Called once when the game session starts.
OnBegin<override>()<suspends> : void =
# Paint all rails blue at session start so they look consistent.
Rail1.SetRailColor(MakeColorFromHex("0055FFFF"))
Rail2.SetRailColor(MakeColorFromHex("0055FFFF"))
Rail3.SetRailColor(MakeColorFromHex("0055FFFF"))
# Make sure all rails are enabled and visible.
Rail1.Enable()
Rail2.Enable()
Rail3.Enable()
Rail1.Show()
Rail2.Show()
Rail3.Show()
# Subscribe to grind events on every rail.
Rail1.StartedGrindingEvent.Subscribe(OnRailStarted)
Rail1.EndedGrindingEvent.Subscribe(OnRailEnded)
Rail2.StartedGrindingEvent.Subscribe(OnRailStarted)
Rail2.EndedGrindingEvent.Subscribe(OnRailEnded)
Rail3.StartedGrindingEvent.Subscribe(OnRailStarted)
Rail3.EndedGrindingEvent.Subscribe(OnRailEnded)
# Fired when any subscribed rail starts being ground.
# The event delivers an `agent` directly (not ?agent) for grind_rail_device.
OnRailStarted(Rider : agent) : void =
# Turn the rail gold while someone is on it.
# Because all three rails share this handler we paint all of them —
# in a real project you'd track which rail fired via separate handlers.
Rail1.SetRailColor(MakeColorFromHex("FFD700FF"))
Rail2.SetRailColor(MakeColorFromHex("FFD700FF"))
Rail3.SetRailColor(MakeColorFromHex("FFD700FF"))
# Fired when the rider leaves any subscribed rail.
OnRailEnded(Rider : agent) : void =
# Award the player one score point for completing a grind.
ScoreManager.Activate(Rider)
# Reset all rails to blue.
Rail1.SetRailColor(MakeColorFromHex("0055FFFF"))
Rail2.SetRailColor(MakeColorFromHex("0055FFFF"))
Rail3.SetRailColor(MakeColorFromHex("0055FFFF"))
Line-by-line highlights:
| Lines | What's happening |
|---|---|
@editable Rail1… |
Declares the three rails as inspector-wirable fields. Without @editable the device has no reference to the placed actors. |
SetRailColor(MakeColorFromHex(…)) |
Paints the rail's neon glow. MakeColorFromHex is a Verse built-in that takes an 8-digit RGBA hex string. |
Enable() / Show() |
Ensures rails are grindable and visible regardless of their saved device settings. |
StartedGrindingEvent.Subscribe(OnRailStarted) |
Registers the class method as the event handler. The handler signature must accept (agent). |
ScoreManager.Activate(Rider) |
Passes the grinding agent to the score manager so the right player gets the point. |
Common patterns
Pattern 1 — Gate a rail behind a puzzle (Enable / Disable)
A locked rail is hidden and disabled at game start. When a player interacts with a button, the rail appears and becomes grindable.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
# Place this device in the level and wire the fields in the Details panel.
rail_gate_device := class(creative_device):
# The rail that should be locked at the start.
@editable
LockedRail : grind_rail_device = grind_rail_device{}
# A button the player interacts with to unlock the rail.
@editable
UnlockButton : button_device = button_device{}
OnBegin<override>()<suspends> : void =
# Disable and hide the rail so players cannot use it yet.
LockedRail.Disable()
LockedRail.Hide()
# When the button is pressed, unlock the rail.
UnlockButton.InteractedWithEvent.Subscribe(OnButtonPressed)
OnButtonPressed(Presser : agent) : void =
# Reveal and enable the rail for everyone.
LockedRail.Show()
LockedRail.Enable()
Pattern 2 — Per-player color change on grind start
Each time a specific player starts grinding, the rail shifts to a unique color to signal ownership — useful in competitive rail-racing modes.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Colors }
rail_color_ownership := class(creative_device):
@editable
RaceRail : grind_rail_device = grind_rail_device{}
# Track whether the rail is currently claimed.
var RailClaimed : logic = false
OnBegin<override>()<suspends> : void =
RaceRail.Enable()
RaceRail.Show()
RaceRail.SetRailColor(MakeColorFromHex("FFFFFFFF")) # White = unclaimed
RaceRail.StartedGrindingEvent.Subscribe(OnGrindStarted)
RaceRail.EndedGrindingEvent.Subscribe(OnGrindEnded)
OnGrindStarted(Rider : agent) : void =
set RailClaimed = true
# Turn the rail red to show it is occupied.
RaceRail.SetRailColor(MakeColorFromHex("FF2200FF"))
OnGrindEnded(Rider : agent) : void =
set RailClaimed = false
# Return to white when the rider leaves.
RaceRail.SetRailColor(MakeColorFromHex("FFFFFFFF"))
Pattern 3 — Timed rail: disable after first grind
A one-shot rail that disables itself the moment a player finishes grinding — great for single-use puzzle elements or limited-time shortcuts.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Verse.org/Colors }
one_shot_rail := class(creative_device):
@editable
SingleUseRail : grind_rail_device = grind_rail_device{}
# Tracks whether the rail has already been used.
var Used : logic = false
OnBegin<override>()<suspends> : void =
SingleUseRail.Enable()
SingleUseRail.Show()
SingleUseRail.SetRailColor(MakeColorFromHex("00FF88FF")) # Green = available
SingleUseRail.EndedGrindingEvent.Subscribe(OnGrindEnded)
OnGrindEnded(Rider : agent) : void =
if (not Used):
set Used = true
# Signal it's spent: turn grey, then hide and disable.
SingleUseRail.SetRailColor(MakeColorFromHex("444444FF"))
SingleUseRail.Disable()
SingleUseRail.Hide()
Gotchas
1. Hide does NOT disable grinding.
Calling Hide() makes the rail invisible but players can still grind on it if it is Enabled. This is intentional (invisible shortcuts!) but easy to misread. If you want to block grinding, always call Disable() as well.
2. EndedGrindingEvent fires on ANY exit — including falling off.
The event fires whether the player reached the end of the rail, jumped off mid-grind, or was knocked off. If your scoring logic should only reward a full grind, you'll need additional state (e.g., track grind start time and only award points if enough time elapsed).
3. Event handler signature is (agent), not (?agent).
StartedGrindingEvent and EndedGrindingEvent are typed listenable(agent) — the handler receives a concrete agent, not an optional ?agent. Do NOT write if (A := Agent?): unwrapping here; that pattern is for listenable(?agent) events.
4. SetRailColor takes a color value, not a string.
Use MakeColorFromHex("RRGGBBAA") (8 hex digits including alpha) or construct a color via MakeColorFromSRGB. Passing a raw string literal will not compile.
5. Always declare rails as @editable fields.
You cannot write grind_rail_device{}.Enable() inline and expect it to affect a placed device. The @editable attribute is what binds your Verse variable to the specific actor placed in the level. Without it you're calling methods on a disconnected default instance.
6. Enable/Disable affect ALL players globally.
These methods toggle the rail for everyone in the session, not per-player. There is no per-agent enable — design your game flow accordingly.