Reference Verse

button_widget: Clickable HUD Buttons in Verse

The `button` widget is a piece of UI you draw directly onto a player's screen — not a physical device in the world, but a HUD element you build and add in Verse. Subscribe to its `OnClick` event to react when the player clicks it, and use `HighlightEvent`/`UnhighlightEvent` to react when they hover. This article shows how to spawn one, wire it up, and glue it to real game state.

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 Knotbutton in ~90 seconds.

Overview

A button is a Verse UI widget — a container that holds a single child widget (usually a text_block) and fires events when the player interacts with it on their HUD. Unlike the physical button_device you place in the world (which players walk up to and interact with for a duration), the button widget lives on the screen and responds to a mouse click or the bound input action.

Reach for the button widget when you want screen-space UI: a Ready Up button in a lobby, a Respawn prompt, a shop Buy button, or a menu the player opens with a key. You build the widget in Verse, add it to a player's screen with player_ui, and subscribe to:

  • OnClick — fires when the player clicks the button. This is the one you'll use most.
  • HighlightEvent — fires when the player's cursor moves onto the button (hover-in).
  • UnhighlightEvent — fires when the cursor leaves the button (hover-out).

All three hand your handler a widget_message, which carries the player who triggered it via the .Player field.

API Reference

button

Button is a container of a single child widget slot and fires the OnClick event when the button is clicked.

Full public surface, resolved verbatim from the live Epic digest (UnrealEngine.digest.verse). Inherited members are merged from widget.

button<native><public> := class<final>(widget):

Events (subscribe a handler to react):

Event Signature Description
OnClick OnClick<public>():listenable(widget_message) Subscribable event that fires when the button is clicked.
HighlightEvent HighlightEvent<public>():listenable(widget_message)
UnhighlightEvent UnhighlightEvent<public>():listenable(widget_message)

widget

Base class for all UI elements drawn on the player's screen.

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

widget<native><public> := class<abstract><unique><epic_internal>:

Walkthrough

Let's build a lobby Ready Up button. When a player joins, we draw a button on their screen. Clicking it opens a vault door (a door_device) for that player and swaps the button label to "READY!". Hovering highlights it. This uses OnClick, HighlightEvent, and UnhighlightEvent — the full event surface.

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

ready_button_device := class(creative_device):

    # The vault door we open when the player clicks Ready
    @editable
    VaultDoor : door_device = door_device{}

    # Localized message helper — button labels take a `message`, not a raw string
    Label<localizes>(S : string) : message = "{S}"

    OnBegin<override>()<suspends> : void =
        # Draw a button for every player already in the game
        for (Player : GetPlayspace().GetPlayers()):
            AddReadyButton(Player)

    AddReadyButton(Player : player) : void =
        if (PlayerUI := GetPlayerUI[Player]):
            # Build the label that sits inside the button
            LabelText := text_block{ DefaultText := Label("READY UP") }
            # The button is a container holding that text as its child
            ReadyBtn := button_loud{}
            ReadyBtn.SetChildWidget(LabelText)

            # Subscribe to all three events. The handlers are methods below.
            ReadyBtn.OnClick().Subscribe(OnReadyClicked)
            ReadyBtn.HighlightEvent().Subscribe(OnReadyHighlighted)
            ReadyBtn.UnhighlightEvent().Subscribe(OnReadyUnhighlighted)

            # Wrap the button in a canvas so we can position it on screen
            Canvas := canvas{}
            Canvas.AddWidget(canvas_slot{
                Widget := ReadyBtn,
                Anchors := anchors{ Minimum := vector2{X := 0.5, Y := 0.85}, Maximum := vector2{X := 0.5, Y := 0.85} },
                Alignment := vector2{X := 0.5, Y := 0.5}
            })

            PlayerUI.AddWidget(Canvas)

    # OnClick hands us a widget_message; read the player off it
    OnReadyClicked(Message : widget_message) : void =
        Player := Message.Player
        # Open the vault door for the player who clicked
        if (Agent := agent[Player]):
            VaultDoor.Open(Agent)

    OnReadyHighlighted(Message : widget_message) : void =
        Print("Player is hovering the Ready button")

    OnReadyUnhighlighted(Message : widget_message) : void =
        Print("Player stopped hovering the Ready button")

Line by line:

  • The using { /Fortnite.com/UI } and /UnrealEngine.com/Temporary/UI imports bring in button_loud, text_block, canvas, and player_ui. Without them the button symbols read as "Unknown identifier".
  • @editable VaultDoor lets you point at a placed door_device in the level from the Details panel — we open it on click via its real Open(Agent) method.
  • Label<localizes>(S:string):message is the localized-text helper. Button labels are message, never raw strings — this converts one for us.
  • In OnBegin, GetPlayspace().GetPlayers() loops every player and calls AddReadyButton to draw their personal button.
  • GetPlayerUI[Player] returns the player_ui for that player (it can fail, hence the if).
  • text_block is the child widget shown inside the button. button_loud is a concrete clickable button; SetChildWidget puts the text inside it.
  • ReadyBtn.OnClick().Subscribe(OnReadyClicked) wires the click. Note OnClick() is a function returning a listenable — you call it, then .Subscribe.
  • The canvas + canvas_slot position the button at the bottom-center of the screen (anchors 0.5/0.85).
  • OnReadyClicked reads Message.Player, converts it to an agent, and calls VaultDoor.Open(Agent) — real game state changes on click.

Common patterns

Pattern 1 — Highlight feedback with HighlightEvent. Play a sound-cue-style log (or trigger a device) when the cursor enters a button.

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

hover_button_device := class(creative_device):

    Label<localizes>(S : string) : message = "{S}"

    OnBegin<override>()<suspends> : void =
        if (Player := GetPlayspace().GetPlayers()[0], UI := GetPlayerUI[Player]):
            Btn := button_loud{}
            Btn.SetChildWidget(text_block{ DefaultText := Label("BUY") })
            Btn.HighlightEvent().Subscribe(OnHovered)
            UI.AddWidget(Btn)

    OnHovered(Message : widget_message) : void =
        Print("Cursor entered the Buy button")

Pattern 2 — Wire a click into a real device (button_device.Enable). Here clicking a HUD button enables a placed physical button_device, unlocking a world interaction.

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

unlock_button_device := class(creative_device):

    @editable
    WorldButton : button_device = button_device{}

    Label<localizes>(S : string) : message = "{S}"

    OnBegin<override>()<suspends> : void =
        # Start with the world button disabled
        WorldButton.Disable()
        if (Player := GetPlayspace().GetPlayers()[0], UI := GetPlayerUI[Player]):
            Btn := button_loud{}
            Btn.SetChildWidget(text_block{ DefaultText := Label("ENABLE TERMINAL") })
            Btn.OnClick().Subscribe(OnUnlockClicked)
            UI.AddWidget(Btn)

    OnUnlockClicked(Message : widget_message) : void =
        # Enable the physical button device so players can now use it
        WorldButton.Enable()
        Print("World terminal enabled")

Pattern 3 — UnhighlightEvent to reset UI state. Track hover exit so you can undo a highlight effect.

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

unhover_button_device := class(creative_device):

    Label<localizes>(S : string) : message = "{S}"

    OnBegin<override>()<suspends> : void =
        if (Player := GetPlayspace().GetPlayers()[0], UI := GetPlayerUI[Player]):
            Btn := button_loud{}
            Btn.SetChildWidget(text_block{ DefaultText := Label("MENU") })
            Btn.HighlightEvent().Subscribe(OnIn)
            Btn.UnhighlightEvent().Subscribe(OnOut)
            UI.AddWidget(Btn)

    OnIn(Message : widget_message) : void =
        Print("Highlighted")

    OnOut(Message : widget_message) : void =
        Print("Reset to normal")

Gotchas

  • OnClick is a function, not a field. You must call it with () before subscribing: Btn.OnClick().Subscribe(Handler). Writing Btn.OnClick.Subscribe(...) will not compile.
  • Handlers receive a widget_message, not an agent. The player is on the message: Message.Player. If you need an agent (for door.Open(Agent), item grants, etc.) convert with if (Agent := agent[Message.Player]):.
  • Button labels are message, never raw strings. Use a Label<localizes>(S:string):message helper — there is no StringToMessage. Passing "BUY" directly where a message is expected fails to compile.
  • A button holds a single child. Use SetChildWidget (or the constructor slot) to place a text_block inside — a bare button with no child renders empty.
  • GetPlayerUI[...] can fail. It returns a value inside an if/failure context; always unwrap it (if (UI := GetPlayerUI[Player]):) before calling AddWidget.
  • The button widget is not the button_device. They share the OnClick/interaction idea but are different types: the widget is drawn on the HUD in Verse; the device is placed in the world and uses InteractedWithEvent. Don't mix their methods.
  • Subscribe in OnBegin (or right after building the widget), and keep references alive. If the widget or your subscription goes out of scope, clicks stop being handled.

Guides & scripts that use button

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

Build your own lesson with button

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 →