Reference Verse compiles

String Interpolation: Live HUD Messages on Your Fortnite Island

String interpolation lets you bake live game data — a player's name, a score, a countdown — directly into a string using curly braces. On its own that's just text, but paired with `hud_message_device` it becomes the cel-shaded speech bubble your pirate cove island needs. This article teaches you the full pipeline: interpolate a string, convert it to a `message`, and push it to a player's screen using the device's real API.

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

Overview

String interpolation lets you inject a value directly into a string literal using curly braces { }. Instead of concatenating pieces with + (which Verse is strict about), you write the whole sentence once and let the compiler fill in the blanks.

Name := "Alice"
Announcement : string = "...And the winner is: {Name}!"

The game problem it solves: almost every player-facing message is partly dynamic. "Welcome, {PlayerName}!", "You have {Coins} coins", "Wave {Round} incoming". Building those by hand with + is painful because Verse does not auto-convert numbers to text — you'd need ToString() everywhere and lots of + glue. Interpolation reads like a sentence and handles the conversion inside the braces.

Key rules to remember:

  • Any expression inside { } must resolve to something with a valid ToString() in scope. A string works directly; a float needs ToString(MyFloat).
  • Verse does NOT auto-convert intfloat, and it won't let you + a number onto a string. Interpolation is the clean path.
  • The result is a plain string. To show it on a device that wants a message (like a HUD), wrap it with a <localizes> helper.

Reach for interpolation whenever the text depends on live game state — a player's name, a score, a countdown, a splash count on the cove.

API Reference

(API surface could not be resolved for this device.)

Walkthrough

Here's the sunny scene: a trigger_device sits at the edge of the dock. Every time a player runs across it and dives into the cove, we bump their personal splash count and flash a HUD banner built entirely with interpolation. We also read a float (their splash "score") and turn it into text with ToString.

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

# A cel-shaded cove: step off the dock, splash into the surf,
# and a banner announces your name and splash count.
cove_dock_device := class(creative_device):

    # The plate at the edge of the dock.
    @editable
    DockPlate : trigger_device = trigger_device{}

    # A localized-message helper: turns a raw string into a `message`.
    MakeMessage<localizes>(S : string) : message = "{S}"

    # Runs once when the game starts.
    OnBegin<override>()<suspends> : void =
        # Subscribe our handler to the plate's fire event.
        DockPlate.TriggeredEvent.Subscribe(OnDockStep)

    # Called each time a player steps on the dock plate.
    OnDockStep(Agent : ?agent) : void =
        if (A := Agent?):
            # Pretend this player has splashed some number of times.
            SplashCount : int = 3
            # A float score we want to show as text.
            SplashScore : float = 42.5

            # Build the banner ENTIRELY with interpolation.
            # ToString turns the float into a string inside the braces.
            Banner : string =
                "Splash #{SplashCount}! Cove score: {ToString(SplashScore)}"

            # Show it on the player's HUD as a localized message.
            if (FortChar := A.GetFortCharacter[]):
                Player := FortChar.GetAgent[]
                ShowBanner(A, Banner)

    # Puts the finished string on screen as a HUD message.
    ShowBanner(A : agent, Text : string) : void =
        if (PlayerUI := GetPlayerUI[A]):
            PlayerUI.ShowMessage(MakeMessage(Text))

Line by line:

  • @editable DockPlate : trigger_device — the placed plate. It MUST be an editable field on a creative_device class so Verse can call its methods; a bare device reference would fail with 'Unknown identifier'.
  • MakeMessage<localizes>(S:string):message = "{S}" — a tiny helper. Device UI wants a message, not a raw string, and there is no StringToMessage. This <localizes> function converts on demand. Note it also uses interpolation ({S}) internally.
  • OnBegin subscribes OnDockStep to DockPlate.TriggeredEvent. Event handlers are methods at class scope; we wire them up here.
  • OnDockStep(Agent : ?agent) — the triggered event hands us an optional agent. We unwrap it with if (A := Agent?): before using it.
  • Banner : string = "Splash #{SplashCount}! Cove score: {ToString(SplashScore)}" — the star of the show. {SplashCount} interpolates an int directly; {ToString(SplashScore)} converts the float to text first, because a bare float has no default text form we can + in.
  • ShowBanner wraps the finished string with MakeMessage and calls PlayerUI.ShowMessage, so the banner actually appears on the diver's screen.

Common patterns

1. Interpolating a float score with ToString. When a value is a float, always call ToString inside the braces — Verse won't convert it silently.

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

score_board_device := class(creative_device):

    @editable
    ReadoutTrigger : trigger_device = trigger_device{}

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

    OnBegin<override>()<suspends> : void =
        ReadoutTrigger.TriggeredEvent.Subscribe(OnRead)

    OnRead(Agent : ?agent) : void =
        if (A := Agent?):
            Distance : float = 128.75
            Line : string = "You dove {ToString(Distance)} meters into the cove!"
            if (UI := GetPlayerUI[A]):
                UI.ShowMessage(AsMessage(Line))

2. Composing several values in one sentence. You can drop many { } slots into a single literal — cleaner than chaining +.

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

welcome_dock_device := class(creative_device):

    @editable
    ArrivalPlate : trigger_device = trigger_device{}

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

    OnBegin<override>()<suspends> : void =
        ArrivalPlate.TriggeredEvent.Subscribe(OnArrive)

    OnArrive(Agent : ?agent) : void =
        if (A := Agent?):
            Wave : int = 2
            Enemies : int = 6
            Reward : float = 150.0
            Brief : string =
                "Wave {Wave}: {Enemies} husks incoming. Survive for {ToString(Reward)} gold!"
            if (UI := GetPlayerUI[A]):
                UI.ShowMessage(ToMessage(Brief))

3. Interpolating right inside the <localizes> message helper. Because the helper body is a string literal, you can build the whole line in one step by passing the pieces in.

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

cliff_banner_device := class(creative_device):

    @editable
    JumpPad : trigger_device = trigger_device{}

    # The interpolation happens inside the localized message body.
    JumpMessage<localizes>(Name : string, Count : int) : message =
        "{Name} launched off the clifftop — jump #{Count}!"

    OnBegin<override>()<suspends> : void =
        JumpPad.TriggeredEvent.Subscribe(OnJump)

    OnJump(Agent : ?agent) : void =
        if (A := Agent?):
            if (UI := GetPlayerUI[A]):
                UI.ShowMessage(JumpMessage("Diver", 5))

Gotchas

  • Numbers don't + onto strings. "Score: " + Score is a compile error. Use "Score: {Score}" instead. For a float, you additionally need "...{ToString(MyFloat)}" because a raw float has no direct text form to splice.
  • No int↔float auto-convert. {SomeInt} is fine on its own, but you can't mix an int where a float is expected. If a value started as a float, keep it a float and use ToString.
  • message is not string. Device UI methods like ShowMessage take a localized message. There is NO StringToMessage. Declare a MyText<localizes>(S:string):message = "{S}" helper and pass your interpolated string through it.
  • Braces are special. { } inside a string always means interpolation. If you genuinely need a literal brace character in text, keep it out of interpolation contexts — don't accidentally leave an empty {}.
  • Unwrap the agent first. The TriggeredEvent handler receives ?agent. Always if (A := Agent?): before building per-player text, or you'll try to read state off a value that might not exist.
  • Expressions inside braces must be valid in scope. {PlayerName} only works if PlayerName is a defined, in-scope value with a ToString. A misspelled name reports 'Unknown identifier' — from inside the string.

Guides & scripts that use hud_message_device

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

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