Reference Devices compiles

popup_dialog_device: HUD Dialogs Players Can Answer

The Pop-Up Dialog device puts a HUD text box on a player's screen — a title, a description, and up to several response buttons. With Verse you can rewrite that text on the fly and react to exactly which button a player clicked, turning a static message into a real interactive choice.

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

Overview

The popup_dialog_device is your go-to device when you want to talk to a player and hear back. It draws a HUD panel — a Title, a Description, and a row of buttons — and fires events when the player sees it, dismisses it, lets it time out, or pushes a specific button.

Reach for it when you want to:

  • Show a tutorial or briefing card at the start of a round.
  • Ask a player a yes/no question ("Open the vault?") and branch on their answer.
  • Build a tiny menu (class select, shop, difficulty) where each button means something.
  • Display live stats by rewriting button text every few seconds.

The key superpower over a plain message device is RespondingButtonEvent, which tells you the agent who clicked and the int index of the button — so a single popup can drive completely different game logic per button.

API Reference

Used to create HUD text boxes that give players information, and allows responses to be customized to player choices.

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

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

Events (subscribe a handler to react):

Event Signature Description
RespondingButtonEvent RespondingButtonEvent<public>:listenable(tuple(agent, int)) Signaled when Button <Index> on this device is pushed by an agent. Sends the agent that pushed the button. Sends the int index of the button that was clicked.
ShownEvent ShownEvent<public>:listenable(agent) Signaled when this device is shown to an agent. Sends the agent looking at the popup.
DismissedEvent DismissedEvent<public>:listenable(agent) Signaled when this device is dismissed by an agent. Sends the agent who dismissed the popup.
TimeOutEvent TimeOutEvent<public>:listenable(agent) Signaled when this device times out while an agent is looking at it. Sends the agent who was looking at the popup.

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.
Show Show<public>(Agent:agent):void Shows the popup to Agent.
Show Show<public>():void Shows the popup to all agents in the experience.
Hide Hide<public>(Agent:agent):void Hides the popup from Agent.
Hide Hide<public>():void Hides the popup from all agents in the experience.
SetButtonCount SetButtonCount<public>(Count:int):void Sets the number of buttons this popup has. Button Count is not updated on active Popups.
GetButtonText GetButtonText<public>(Index:int)<transacts>:string Returns the Button Text for this popup at a specified index.
SetButtonText SetButtonText<public>(Text:message, Index:int):void Sets the Button Text for a button at a specific index on this popup. * Text should be no more than 24 characters. * If Text is empty the button will show OK instead. * Button 1 uses Index 0.
SetDescriptionText SetDescriptionText<public>(Text:message):void Sets the Description text for this popup. Text should be no more than 350 characters.
GetDescriptionText GetDescriptionText<public>()<transacts>:string Returns the Description text for this popup.
SetTitleText SetTitleText<public>(Text:message):void Sets the Title text for this popup. Text should be no more than 32 characters.
GetTitleText GetTitleText<public>()<transacts>:string Returns the Title text for this popup.

Walkthrough

Let's build a vault entrance. When a player steps on a trigger, a popup asks "Open the Vault?" with two buttons: Open it and Walk away. If they pick Open it, we unlock the vault door; if they walk away (or dismiss the popup), nothing happens.

We need three placed devices wired into our class: the popup, a trigger, and a prop-manipulator-style door we'll just enable/disable. For the door we'll use a barrier_device so the example stays self-contained.

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

vault_dialog := class(creative_device):

    @editable
    VaultPopup : popup_dialog_device = popup_dialog_device{}

    @editable
    EntryTrigger : trigger_device = trigger_device{}

    @editable
    VaultDoor : barrier_device = barrier_device{}

    # Localized message helper — message params can't take raw strings.
    DialogText<localizes>(S : string) : message = "{S}"

    OnBegin<override>()<suspends> : void =
        # Configure the popup before anyone sees it.
        VaultPopup.SetButtonCount(2)
        VaultPopup.SetTitleText(DialogText("Sealed Vault"))
        VaultPopup.SetDescriptionText(DialogText("You found the vault. Open it?"))
        VaultPopup.SetButtonText(DialogText("Open it"), 0)
        VaultPopup.SetButtonText(DialogText("Walk away"), 1)

        # The door starts closed (enabled = blocking).
        VaultDoor.Enable()

        # When a player steps on the trigger, show the popup to them.
        EntryTrigger.TriggeredEvent.Subscribe(OnEntered)

        # React to whichever button gets pushed.
        VaultPopup.RespondingButtonEvent.Subscribe(OnButtonPushed)

        # Optional: if they dismiss it, log nothing happened.
        VaultPopup.DismissedEvent.Subscribe(OnDismissed)

    OnEntered(MaybeAgent : ?agent) : void =
        if (Player := MaybeAgent?):
            VaultPopup.Show(Player)

    OnButtonPushed(Result : tuple(agent, int)) : void =
        Player := Result(0)
        Index := Result(1)
        if (Index = 0):
            # "Open it" — drop the barrier so they can walk in.
            VaultDoor.Disable()
            VaultPopup.Hide(Player)
        else:
            # "Walk away" — just close the popup.
            VaultPopup.Hide(Player)

    OnDismissed(Agent : agent) : void =
        # Player closed the popup without choosing; nothing to do.
        VaultPopup.Hide(Agent)

Line by line:

  • The three @editable fields let you drop in your placed devices in the UEFN details panel. Without these fields, calling VaultPopup.Show(...) would fail with Unknown identifier — you can only call a device you hold a reference to.
  • DialogText<localizes>(S:string):message is the bridge from a plain string to the message type that SetTitleText/SetDescriptionText/SetButtonText require. There is no StringToMessage.
  • In OnBegin we configure the popup before showing it: SetButtonCount(2) must be set while the popup is inactive (it doesn't update on already-shown popups). Button 1 is Index 0, Button 2 is Index 1.
  • EntryTrigger.TriggeredEvent hands us a ?agent. We unwrap it with if (Player := MaybeAgent?) and only then call VaultPopup.Show(Player) to show the popup to that player.
  • RespondingButtonEvent is a listenable(tuple(agent, int)), so the handler receives one tuple value. Result(0) is the clicking agent; Result(1) is the button index. We branch on the index to open the vault or just close.
  • DismissedEvent gives us a bare agent (already unwrapped) so we hide the popup for them.

Common patterns

Reading current text with the getters

The getters (GetTitleText, GetDescriptionText, GetButtonText) are <transacts>, so they must be called from a context that allows the transacts effect — here inside a normal method works because reads are pure. Useful for swapping text only when it changed.

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

briefing_board := class(creative_device):

    @editable
    Popup : popup_dialog_device = popup_dialog_device{}

    @editable
    ShowButton : button_device = button_device{}

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

    OnBegin<override>()<suspends> : void =
        Popup.SetButtonCount(1)
        Popup.SetTitleText(Loc("Mission Briefing"))
        Popup.SetDescriptionText(Loc("Reach the rooftop before the timer ends."))
        Popup.SetButtonText(Loc("Got it"), 0)
        ShowButton.InteractedWithEvent.Subscribe(OnInteract)

    OnInteract(Agent : agent) : void =
        # Read the current title back out, then show to this player.
        CurrentTitle := Popup.GetTitleText()
        if (CurrentTitle = "Mission Briefing"):
            Popup.SetTitleText(Loc("Updated Briefing"))
        Popup.Show(Agent)

Showing to everyone and handling a timeout

The no-argument Show() broadcasts to every player. TimeOutEvent fires if a player lets the popup expire without answering — handy for default outcomes.

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

round_announce := class(creative_device):

    @editable
    Announcement : popup_dialog_device = popup_dialog_device{}

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

    OnBegin<override>()<suspends> : void =
        Announcement.Enable()
        Announcement.SetButtonCount(1)
        Announcement.SetTitleText(Loc("Round Start"))
        Announcement.SetDescriptionText(Loc("Storm closes in 60 seconds!"))
        Announcement.SetButtonText(Loc("Ready"), 0)

        Announcement.ShownEvent.Subscribe(OnShown)
        Announcement.TimeOutEvent.Subscribe(OnTimedOut)

        # Broadcast to all players at once.
        Announcement.Show()

    OnShown(Agent : agent) : void =
        # Could grant a buff, start a per-player timer, etc.
        Announcement.Hide(Agent)

    OnTimedOut(Agent : agent) : void =
        # Player ignored the prompt — treat as auto-ready.
        Announcement.Hide(Agent)

Live stat panel using SetButtonText per slot

Rewriting each button's text turns the popup into a stat readout — exactly the Speedway template pattern. Buttons here act as labelled rows.

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

stats_panel := class(creative_device):

    @editable
    StatsPopup : popup_dialog_device = popup_dialog_device{}

    @editable
    OpenButton : button_device = button_device{}

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

    OnBegin<override>()<suspends> : void =
        StatsPopup.SetButtonCount(3)
        StatsPopup.SetTitleText(Loc("Your Stats"))
        OpenButton.InteractedWithEvent.Subscribe(OnOpen)

    OnOpen(Agent : agent) : void =
        # In a real game these numbers come from stored player stats.
        StatsPopup.SetButtonText(Loc("Eliminations: 7"), 0)
        StatsPopup.SetButtonText(Loc("Wins: 2"), 1)
        StatsPopup.SetButtonText(Loc("Best Time: 41s"), 2)
        StatsPopup.Show(Agent)

Gotchas

  • message, not string. Every text setter (SetTitleText, SetDescriptionText, SetButtonText) takes a message. Pass strings through a <localizes> helper like Loc<localizes>(S:string):message = "{S}". There is no StringToMessage function.
  • SetButtonCount won't update an active popup. Set the count in OnBegin (or before Show). Changing it while the popup is on screen does nothing for that showing.
  • Button indices are 0-based. "Button 1" in the details panel is Index 0. RespondingButtonEvent reports that same 0-based index in Result(1).
  • Unwrap the tuple correctly. RespondingButtonEvent is listenable(tuple(agent, int)). The handler takes a single tuple(agent, int) parameter; pull the agent with Result(0) and index with Result(1). It is NOT a ?agent.
  • Trigger gives ?agent, popup events give agent or tuple. A trigger_device's TriggeredEvent hands you ?agent — you must if (P := MaybeAgent?). But ShownEvent/DismissedEvent/TimeOutEvent already hand you a plain agent, so no unwrap is needed.
  • Text length limits. Title ≤ 32 chars, button text ≤ 24 chars, description ≤ 350 chars. An empty button text falls back to showing OK.
  • You must hold a device reference. Declare the device as an @editable field and assign it in the UEFN details panel. Calling methods on an un-referenced device is an Unknown identifier compile error.

Device Settings & Options

The popup_dialog_device User Options panel in the UEFN editor — every setting you can tune.

Popup Dialog Device settings and options panel in the UEFN editor — Title, Content Alignment, Description, Auto Display, Response Type
Popup Dialog Device — User Options in the UEFN editor: Title, Content Alignment, Description, Auto Display, Response Type
⚙️ Settings on this device (5)

Setting names read from the panel above — may be partial; the screenshots are the source of truth.

Title
Content Alignment
Description
Auto Display
Response Type

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