Talk to Players: HUD Message Device

In this lesson you'll learn to

  • Student can show, update, and hide on-screen messages from Verse via hud_message_device (the UI arc's first rung).

Student can show, update, and hide on-screen messages from Verse via hud_message_device (the UI arc's first rung).

🧩 Your capstone piece: All hunt feedback text: welcome banner, shell-count updates, winner announcement

Walkthrough

Overview

The hud_message_device solves a fundamental game-design problem: players need feedback. When a guard spots them, when the final zone opens, when they earn a bonus β€” they need to know. The HUD message device lets you surface that information as an on-screen text overlay without building custom UI from scratch.

Key capabilities:

  • Show to everyone (Show()) or show to one player (Show(Agent)) β€” great for personal score updates vs. global announcements.
  • Inline custom text at runtime via SetText(Text:message) or the overloaded Show(Agent, Message, ?DisplayTime) / Show(Message, ?DisplayTime) β€” no need to pre-bake every string in the editor.
  • Control display duration with SetDisplayTime / GetDisplayTime; pass 0.0 to pin the message permanently.
  • React to lifecycle events β€” ShowMessageEvent, HideMessageEvent, and ClearAllMessagesEvent let your Verse code respond when messages appear or disappear.
  • Clean up with Hide(), Hide(Agent), or ClearAllMessages() when the moment has passed.

Reach for this device whenever you need lightweight, event-driven text feedback: countdown timers, wave announcements, per-player kill streaks, objective updates, or tutorial hints.

API Reference

hud_message_device

Used to show custom HUD messages to one or more agents.

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

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

Events (subscribe a handler to react):

Event Signature Description
ShowMessageEvent ShowMessageEvent<public>:listenable(agent) Called when a Message has been Shown on-screen. Returns an Agent if it was Shown on a specified Agent's screen.
HideMessageEvent HideMessageEvent<public>:listenable(agent) Called when a Message has been Hidden on-screen. Returns an Agent if it was Hidden from a specified Agent's screen.
ClearAllMessagesEvent ClearAllMessagesEvent<public>:listenable(agent) Called when all queued Messages from all players that are affected by this HUD Message Device have been cleared.

Methods (call these to make the device act):

Method Signature Description
Show Show<public>(Agent:agent):void Shows the currently set HUD Message on Agents screen. Will replace any previously active message. Use this when the device is setup to target specific agents.
Show Show<public>():void Shows the currently set Message HUD message on screen. Will replace any previously active message.
Hide Hide<public>():void Hides the HUD message.
Hide Hide<public>(Agent:agent):void Hides the currently set HUD Message on Agents screen. Use this when the device is setup to target specific agents.
Show Show<public>(Agent:agent, Message:message, ?DisplayTime:float Displays a Custom message to a specific Agent that you define.Setting DisplayTime to 0.0 will display the HUD message persistently.If not defined, or less than 0.0 the message will show for the time set on the device.
Show Show<public>(Message:message, ?DisplayTime:float Displays a Custom message that you define for all PlayersSetting DisplayTime to 0.0 will display the HUD message persistently.If not defined, or less than 0.0 the message will show for the time set on the device.
SetDisplayTime SetDisplayTime<public>(Time:float):void Sets the time (in seconds) the HUD message will be displayed. 0.0 will display the HUD message persistently.
GetDisplayTime GetDisplayTime<public>()<transacts>:float Returns the time (in seconds) for which the HUD message will be displayed. 0.0 means the message is displayed persistently.
SetText SetText<public>(Text:message):void Sets the Message to be displayed when the HUD message is activated. Text is clamped to 150 characters.
ClearAllMessages ClearAllMessages<public>():void Clears all queued Messages from all players that are affected by this HUD Message Device.

Walkthrough

Scenario: Vault Alert System

A player steps on a pressure plate. The vault door opens, and:

  1. A global "Vault Opened!" message flashes for 3 seconds.
  2. The player who triggered it gets a personal persistent message: "You found the vault β€” grab the loot!"
  3. When that personal message is hidden, we log it via HideMessageEvent.

This walkthrough uses SetText, SetDisplayTime, Show(), Show(Agent, Message, ?DisplayTime:=...), Hide(Agent), HideMessageEvent, and ClearAllMessages.

vault_alert_device := class(creative_device):

    # Wire these up in the UEFN editor
    @editable
    Plate : trigger_device = trigger_device{}

    # One device for the global broadcast, one for the personal tip
    @editable
    GlobalHUD : hud_message_device = hud_message_device{}

    @editable
    PersonalHUD : hud_message_device = hud_message_device{}

    # Localizer helper β€” message params must be of type `message`
    VaultOpened<localizes>(S : string) : message = "{S}"
    PersonalTip<localizes>(S : string) : message = "{S}"

    OnBegin<override>()<suspends> : void =
        # Subscribe to the pressure plate
        Plate.TriggeredEvent.Subscribe(OnPlateTriggered)

        # React when the personal message is hidden
        PersonalHUD.HideMessageEvent.Subscribe(OnPersonalMessageHidden)

        # Pre-configure the global HUD: 3-second flash
        GlobalHUD.SetDisplayTime(3.0)
        GlobalHUD.SetText(VaultOpened("⚠ Vault Opened!"))

        # Personal HUD will be shown persistently (DisplayTime = 0.0)
        # We'll pass that inline when we call Show

    # Handler called when a player steps on the plate
    # trigger_device fires listenable(?agent)
    OnPlateTriggered(Agent : ?agent) : void =
        # 1. Global announcement to every player
        GlobalHUD.Show()

        # 2. Personal persistent message for the triggering player only
        if (A := Agent?):
            PersonalHUD.Show(A, PersonalTip("You found the vault β€” grab the loot!"), ?DisplayTime := 0.0)

    # Called when the personal message is hidden for any agent
    OnPersonalMessageHidden(A : agent) : void =
        # Clean up any remaining queued messages across all players
        PersonalHUD.ClearAllMessages()

Line-by-line breakdown:

Line(s) What it does
@editable Plate Wires the pressure plate placed in the level.
@editable GlobalHUD / PersonalHUD Two separate hud_message_device instances β€” one for everyone, one per-player.
VaultOpened<localizes> Wraps a raw string into a message β€” required for any method that takes message.
GlobalHUD.SetDisplayTime(3.0) Tells the global device to auto-hide after 3 seconds.
GlobalHUD.SetText(...) Pre-loads the text so Show() has something to display.
GlobalHUD.Show() Broadcasts to all players simultaneously.
PersonalHUD.Show(A, ..., ?DisplayTime := 0.0) Shows a custom inline message to one agent, pinned permanently (0.0).
PersonalHUD.HideMessageEvent.Subscribe(...) Fires whenever the personal message is hidden on any screen.
PersonalHUD.ClearAllMessages() Wipes the queue for all affected players β€” good housekeeping.

Common patterns

Pattern 1 β€” Dynamic countdown using SetText + SetDisplayTime

Update the HUD message every second to show a live countdown, then clear it when time is up.

countdown_hud_device := class(creative_device):

    @editable
    CountdownHUD : hud_message_device = hud_message_device{}

    CountdownText<localizes>(N : int) : message = "Round starts in {N}..."
    GoText<localizes>(S : string) : message = "{S}"

    OnBegin<override>()<suspends> : void =
        # Pin the message β€” we'll clear it manually
        CountdownHUD.SetDisplayTime(0.0)

        var SecondsLeft : int = 5
        loop:
            if (SecondsLeft <= 0):
                break
            CountdownHUD.SetText(CountdownText(SecondsLeft))
            CountdownHUD.Show()
            Sleep(1.0)
            set SecondsLeft = SecondsLeft - 1

        # Show "GO!" for 2 seconds then clear
        CountdownHUD.SetDisplayTime(2.0)
        CountdownHUD.SetText(GoText("GO!"))
        CountdownHUD.Show()
        Sleep(2.0)
        CountdownHUD.ClearAllMessages()

Covers: SetText, SetDisplayTime, Show(), ClearAllMessages


Pattern 2 β€” Per-player elimination streak with Show(Agent, Message)

When a player gets an elimination, show them a personal streak message without interrupting other players' HUDs.

streak_hud_device := class(creative_device):

    @editable
    EliminationManager : elimination_manager_device = elimination_manager_device{}

    @editable
    StreakHUD : hud_message_device = hud_message_device{}

    StreakMsg<localizes>(N : int) : message = "Elimination streak: {N}!"

    # Track per-player streak counts
    var Streaks : [agent]int = map{}

    OnBegin<override>()<suspends> : void =
        EliminationManager.EliminationEvent.Subscribe(OnElimination)

    OnElimination(Result : elimination_result) : void =
        if (Eliminator := Result.EliminatingAgent?):
            CurrentStreak : int =
                if (S := Streaks[Eliminator]):
                    S
                else:
                    0
            NewStreak := CurrentStreak + 1
            if (set Streaks[Eliminator] = NewStreak) {}
            # Show personal message for 2.5 seconds
            StreakHUD.Show(Eliminator, StreakMsg(NewStreak), ?DisplayTime := 2.5)

Covers: Show(Agent, Message, ?DisplayTime)


Pattern 3 β€” React to ShowMessageEvent and hide for a specific agent

Listen for when any message appears, then hide it for a specific VIP agent who shouldn't see spoilers.

vip_filter_hud_device := class(creative_device):

    @editable
    AnnouncementHUD : hud_message_device = hud_message_device{}

    # The VIP player agent reference (set via game logic elsewhere)
    var VIPAgent : ?agent = false

    OnBegin<override>()<suspends> : void =
        AnnouncementHUD.ShowMessageEvent.Subscribe(OnMessageShown)

        # Simulate acquiring a VIP after 2 seconds
        Sleep(2.0)
        Playspace := GetPlayspace()
        Players := Playspace.GetPlayers()
        if (First := Players[0]):
            set VIPAgent = option{First.GetAgent[]}

        # Broadcast a message to everyone
        AnnouncementHUD.SetDisplayTime(5.0)
        AnnouncementHUD.SetText(SpoilerText("Boss location revealed!"))
        AnnouncementHUD.Show()

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

    # Fires for each agent the message is shown to
    OnMessageShown(A : agent) : void =
        # If this is our VIP, immediately hide it for them
        if (VIP := VIPAgent?):
            if (A = VIP):
                AnnouncementHUD.Hide(VIP)

Covers: ShowMessageEvent, SetText, SetDisplayTime, Show(), Hide(Agent)


Gotchas

1. message is NOT a string β€” use <localizes>

Every method that takes text (SetText, Show(Agent, Message, ...), Show(Message, ...)) expects a message type, not a plain string. There is no StringToMessage function. You must declare a localizer:

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

Then call SetText(MyLabel("Hello!")). Passing a raw string literal directly will fail to compile.

2. DisplayTime := 0.0 means forever, not "instant hide"

Passing 0.0 to SetDisplayTime or the ?DisplayTime parameter pins the message on screen indefinitely. You must call Hide(), Hide(Agent), or ClearAllMessages() to remove it. This is intentional and useful for persistent objective text, but easy to forget.

3. Show() replaces the active message β€” queue carefully

Calling Show() while a message is already visible will replace it immediately. If you need sequential messages, Sleep between calls or use GetDisplayTime() to know when the current one expires.

4. Unwrap ?agent before calling Show(Agent)

Events like trigger_device.TriggeredEvent fire listenable(?agent) β€” an optional agent. You must unwrap it before passing to Show(Agent:agent):

OnTriggered(MaybeAgent : ?agent) : void =
    if (A := MaybeAgent?):
        MyHUD.Show(A)  # safe β€” A is agent, not ?agent

Passing ?agent directly to a method expecting agent is a compile error.

5. ClearAllMessagesEvent fires with an agent parameter

Despite clearing all messages, ClearAllMessagesEvent is typed listenable(agent). Your handler must accept an agent argument. It represents one of the affected agents β€” don't assume it's a specific player.

6. Text is clamped to 150 characters

SetText silently clamps its input. If your dynamic string might exceed 150 characters, truncate it in Verse before passing it in β€” there's no error or event to warn you.

7. Use two devices for global + per-player simultaneously

You cannot send a global Show() and a targeted Show(Agent) from the same device instance in the same tick and have both work independently. Use two separate hud_message_device instances β€” one configured for all players, one for targeted messages.

πŸ΄β€β˜ οΈ

Take on the Challenge

Pass the 5-question challenge to master this lesson and chart the quest in your journal.

Recap

One step closer to Shell-Hunt β€” All hunt feedback text: welcome banner, shell-count updates, winner announcement

Pass the quiz above to chart this quest in your Journal.
Source
Verse Island

Β© Biloxi Studios Inc. β€” original Verse Island content.

Sources & licensing

Turn this into a guided course

Add Talk to Players: HUD Message Device to your free study plan β€” we'll suggest related pages and stitch the lot into one compile-checked, self-guided lesson with worked examples and quizzes.

🧭 The Keeper's log

Quest complete? Chart your next heading from the 🦩 South Shores (Free) expedition.