Reference Devices

rng_device: Random Rolls That Drive Your Game

Want a slot machine, a loot crate with random rewards, or a coin-flip door? The rng_device rolls a random number between two limits and fires events for win, lose, max, and min. This guide shows you how to drive it from Verse.

Updated
The code on this reference page is provided as-is and did not pass the latest compile check — treat the examples as a starting point and verify in your project.
Watch the Knotrng_device in ~90 seconds.

Overview

The rng_device is UEFN's built-in random number generator. You configure a Value Limit 1 (minimum) and Value Limit 2 (maximum) plus a Winning Value threshold in the Details panel, then call Activate() to roll. Depending on what comes up, the device signals one of four events:

  • WinEvent — the roll was >= Winning Value.
  • LoseEvent — the roll was < Winning Value.
  • RolledMaxEvent — the roll hit the configured maximum exactly.
  • RolledMinEvent — the roll hit the configured minimum exactly.

Reach for the rng_device whenever you want server-authoritative randomness without rolling your own math: a casino slot machine, a mystery reward chest, a 1-in-100 jackpot, a random spawn picker, or a coin-flip mechanic that decides which door opens. Because the device handles the threshold comparison for you, you just subscribe to the event you care about and run your game logic in the handler.

Note there are two Activate overloads: Activate(Agent:agent) (roll on behalf of a specific player — useful when you want to know who rolled) and Activate() (roll with no agent context). You can Enable/Disable the device to gate rolling, and Cancel() to stop an in-progress generation.

API Reference

rng_device

Used to generate random numbers between a minimum and maximum value. Events are signaled when numbers are generated. * Value Limit 1 is the minimum value for generation. * Value Limit 2 is the maximum value for generation.

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

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

Events (subscribe a handler to react):

Event Signature Description
WinEvent WinEvent<public>:listenable(tuple()) Signaled when the generated number >= Winning Value.
LoseEvent LoseEvent<public>:listenable(tuple()) Signaled when the generated number < Winning Value.
RolledMaxEvent RolledMaxEvent<public>:listenable(tuple()) Signaled when the generated number = maximum.
RolledMinEvent RolledMinEvent<public>:listenable(tuple()) Signaled when the generated number = minimum.

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.
Activate Activate<public>(Agent:agent):void Randomly generate a number between Value Limit 1 and Value Limit 2. * If the number is >= Winning Value then WinEvent is fired. * If the number is < Winning Value then LoseEvent is fired. * If the number = minimum then `RolledMi
Activate Activate<public>():void Randomly roll a number within the configured min + max value range. * If the number is >= Winning Value then WinEvent is fired. * If the number is < Winning Value then LoseEvent is fired. * If the number = minimum then `RolledMinEve
Cancel Cancel<public>():void Cancels the active number generation.

Walkthrough

Let's build a mystery loot crate. A trigger sits under the crate; when a player steps on it, we activate the RNG. On a WinEvent we grant a rare reward by triggering an item granter; on a LoseEvent the player gets the common reward. If they hit the absolute jackpot (RolledMaxEvent) we celebrate with a separate VFX trigger.

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

loot_crate := class(creative_device):

    # The RNG that decides the reward tier.
    @editable
    RNG : rng_device = rng_device{}

    # Player steps on this to roll.
    @editable
    RollTrigger : trigger_device = trigger_device{}

    # Fires the rare reward (e.g. an item_granter wired to its Trigger).
    @editable
    RareReward : trigger_device = trigger_device{}

    # Fires the common reward.
    @editable
    CommonReward : trigger_device = trigger_device{}

    # Plays jackpot celebration VFX/sound.
    @editable
    JackpotFX : trigger_device = trigger_device{}

    OnBegin<override>()<suspends>:void =
        # When a player steps on the plate, roll the RNG for that player.
        RollTrigger.TriggeredEvent.Subscribe(OnPlayerStepped)
        # React to each possible outcome.
        RNG.WinEvent.Subscribe(OnWin)
        RNG.LoseEvent.Subscribe(OnLose)
        RNG.RolledMaxEvent.Subscribe(OnJackpot)

    # TriggeredEvent hands us a (Agent : agent) — roll for that player.
    OnPlayerStepped(Agent : agent):void =
        RNG.Activate(Agent)

    OnWin():void =
        RareReward.Trigger()

    OnLose():void =
        CommonReward.Trigger()

    OnJackpot():void =
        # RolledMaxEvent ALSO fires alongside WinEvent when the max is the top,
        # so use it for the extra celebration only.
        JackpotFX.Trigger()

Line by line:

  • RNG : rng_device = rng_device{} — the @editable field that lets you drag your placed RNG device onto this script in UEFN. Without an @editable field, calling RNG.Activate() would fail with Unknown identifier.
  • The other @editable trigger_device fields are how we cause real effects: granters/VFX are wired to these triggers in the editor, and Trigger() fires them.
  • In OnBegin, we Subscribe handlers to the trigger and to three RNG events. Subscriptions live in OnBegin; the handlers are methods at class scope.
  • OnPlayerStepped(Agent : agent)TriggeredEvent is a listenable(agent), so the handler receives a plain agent. We pass it straight into RNG.Activate(Agent) so the roll is associated with that player.
  • OnWin / OnLose / OnJackpot take no parameters because the RNG events are listenable(tuple()) — they carry no payload. We just Trigger() the appropriate reward device.

Common patterns

Coin flip with Activate() (no agent)

Use the no-arg Activate() when the roll isn't tied to a specific player — like a global coin flip that picks which of two doors opens. Wire WinEvent to the left door and LoseEvent to the right.

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

coin_flip := class(creative_device):

    @editable
    RNG : rng_device = rng_device{}

    @editable
    FlipButton : button_device = button_device{}

    @editable
    LeftDoor : trigger_device = trigger_device{}

    @editable
    RightDoor : trigger_device = trigger_device{}

    OnBegin<override>()<suspends>:void =
        FlipButton.InteractedWithEvent.Subscribe(OnFlip)
        RNG.WinEvent.Subscribe(OnHeads)
        RNG.LoseEvent.Subscribe(OnTails)

    OnFlip(Agent : agent):void =
        # No agent needed — this is a global flip.
        RNG.Activate()

    OnHeads():void =
        LeftDoor.Trigger()

    OnTails():void =
        RightDoor.Trigger()

Rare jackpot with RolledMinEvent and a re-roll cooldown

Here we gate rolling with Disable/Enable so a player can't spam the slot machine, and we react to RolledMinEvent for a "worst possible" consolation.

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

slot_machine := class(creative_device):

    @editable
    RNG : rng_device = rng_device{}

    @editable
    PullLever : button_device = button_device{}

    @editable
    BadLuckFX : trigger_device = trigger_device{}

    OnBegin<override>()<suspends>:void =
        PullLever.InteractedWithEvent.Subscribe(OnPull)
        RNG.RolledMinEvent.Subscribe(OnSnakeEyes)

    OnPull(Agent : agent):void =
        # Roll for this player, then briefly lock the machine.
        RNG.Activate(Agent)
        RNG.Disable()
        Sleep(3.0)
        RNG.Enable()

    OnSnakeEyes():void =
        BadLuckFX.Trigger()

Cancelling an in-progress roll

Cancel() stops the active generation — handy if you give players a "chicken out" button before the result lands.

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

cancelable_roll := class(creative_device):

    @editable
    RNG : rng_device = rng_device{}

    @editable
    RollButton : button_device = button_device{}

    @editable
    AbortButton : button_device = button_device{}

    OnBegin<override>()<suspends>:void =
        RollButton.InteractedWithEvent.Subscribe(OnRoll)
        AbortButton.InteractedWithEvent.Subscribe(OnAbort)

    OnRoll(Agent : agent):void =
        RNG.Activate(Agent)

    OnAbort(Agent : agent):void =
        RNG.Cancel()

Gotchas

  • The RNG events carry no payload. WinEvent, LoseEvent, RolledMaxEvent, and RolledMinEvent are listenable(tuple()), so their handlers take no parameters — write OnWin():void, not OnWin(Agent:agent). If you need to know who rolled, capture the agent from the trigger/button handler and pass it to Activate(Agent); the win/lose events themselves won't hand it back.
  • Max/min events fire in addition to win/lose. If the maximum value is also above the Winning Value, then a max roll fires both WinEvent and RolledMaxEvent. Don't double-grant rewards — use the max/min events for extra flair, not the core reward logic.
  • Two Activate overloads. Activate(Agent:agent) and Activate() are different functions. Pick the agent overload only when you actually have an agent; passing nothing to the agent version won't compile.
  • You must declare the device as an @editable field. A bare rng_device.Activate() fails with Unknown identifier. Declare RNG : rng_device = rng_device{} in your class(creative_device) and drag your placed device onto it in UEFN.
  • Configure limits in the Details panel, not Verse. Value Limit 1, Value Limit 2, and Winning Value are editor properties — Verse only triggers the roll and reacts to the outcome. If your WinEvent never fires, check that the Winning Value is reachable within your min/max range.
  • Disable() blocks rolling. While disabled, calling Activate() does nothing. Remember to Enable() again (as in the slot-machine cooldown example) or the device stays silent.

Guides & scripts that use rng_device

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

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