Shout into the Void: print/log debugging

In this lesson you'll learn to

  • βœ“Student can instrument any Verse script with Print statements and read the output log to trace game flow and diagnose bugs.

Student can instrument any Verse script with Print statements and read the output log to trace game flow and diagnose bugs.

πŸ“– Reference & full walkthrough: Shout into the Void: print/log debugging

πŸ” Builds on: north-jungle: verse language fundamentals (first-script, functions)

🧩 Your capstone piece: The RaceDebug logger used in every later step (toggleable debug overlay of race state)


What you'll learn

You'll learn how to use Print() for log-based tracing with string interpolation, and how to surface those same debug values on-screen by building a canvas with a text_block and adding it to a player's UI via GetPlayerUI[] / AddWidget. Every button press updates both the log and the widget, so you can watch state change without squinting at the console.

How it works

Print() writes a single string to the Output Log (and screen). Its most important rules:

  • One string only. Never pass comma-separated arguments. Combine values with string interpolation {...} β€” the braces evaluate the expression and convert it to text: Print("2 + 2 = {2 + 2}") logs 2 + 2 = 4.
  • No + on messages. Build output with interpolation, not concatenation.
  • Top-to-bottom execution. The order your prints appear tells you the order your code ran β€” the cheapest way to see how far execution got.

The log is great for you, but invisible to players. To show debug text on screen we use the player UI:

  • Player.GetPlayerUI[] is fallible ([]), so bind it inside an if: if (UI := Player.GetPlayerUI[]):.
  • Build a canvas whose slot holds a text_block, then call UI.AddWidget(Canvas).
  • Keep a reference to the text_block and call .SetText(...) to update it live. SetText takes a message, so we wrap interpolated text with a <localizes> helper.

Let's build it

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

# A debug device: logs with Print() AND mirrors values on an on-screen widget.
debug_print_device := class<concrete>(creative_device):

    # Drag a Button device into this slot in the Details panel.
    @editable TriggerButton : button_device = button_device{}

    # Mutable counter so we can watch state change across presses.
    var PressCount : int = 0

    # The on-screen text widget we update live. Created in OnBegin.
    var DebugText : text_block = text_block{}

    # <localizes> helper turns interpolated text into a message for SetText.
    MakeMessage<localizes>(Value : string) : message = "{Value}"

    OnBegin<override>()<suspends> : void =
        # 1. Prove OnBegin actually ran.
        Print("[Debug] debug_print_device started!")

        # 2. Interpolate a value and a calculation into the log.
        Counter : int = 42
        Print("[Debug] Counter = {Counter}, Doubled = {Counter * 2}")

        # 3. Build the on-screen widget and add it to every player's UI.
        set DebugText = text_block{DefaultText := MakeMessage("[Debug] Ready. Presses: 0")}
        Canvas := canvas:
            Slots := array:
                canvas_slot:
                    Anchors := anchors{Minimum := vector2{X := 0.05, Y := 0.05}, Maximum := vector2{X := 0.05, Y := 0.05}}
                    Offsets := margin{Top := 0.0, Left := 0.0, Right := 0.0, Bottom := 0.0}
                    Alignment := vector2{X := 0.0, Y := 0.0}
                    SizeToContent := true
                    Widget := DebugText
        for (Player : GetPlayspace().GetPlayers()):
            if (PlayerUI := GetPlayerUI[Player]):
                PlayerUI.AddWidget(Canvas)

        # 4. Subscribe so each press updates log AND widget.
        TriggerButton.InteractedWithEvent.Subscribe(OnButtonPressed)

    # Handler signature must match the button event: (agent):void.
    OnButtonPressed(Agent : agent) : void =
        set PressCount = PressCount + 1
        # Log it...
        Print("[Debug] Button pressed. PressCount = {PressCount}")
        # ...and mirror it on the screen widget.
        DebugText.SetText(MakeMessage("[Debug] Presses: {PressCount}"))```

## Try it yourself

1. Create a new Verse device in UEFN and paste in the code above.
2. Build Verse, then drag `debug_print_device` into your island.
3. Place a **Button** device and assign it to the `TriggerButton` slot.
4. Launch a session. Watch the Output Log for the `[Debug]` startup and counter lines, and confirm the on-screen text appears at the top-left.
5. Press the button repeatedly β€” the log AND the widget should both show `PressCount` climbing.
6. Change `Counter` or the `* 2` math, rebuild, and confirm the interpolated output updates in the log.

## Recap

- `Print()` takes exactly **one `string`**; use **string interpolation** `{...}` for values and calculations β€” never `+`, never comma-separated args.
- `GetPlayerUI[]` is fallible β€” bind it with `if (UI := Player.GetPlayerUI[]):` before calling `AddWidget`.
- Build a `canvas` containing a `text_block`, add it with `AddWidget`, and call `.SetText(...)` (with a `<localizes>` message) to update debug text live on screen.
- Print at the start of `OnBegin` and inside handlers to verify which code ran and in what order.
πŸ”’

Keep going β€” free

You've read the intro. The rest of this lesson is free for members. Sign in to continue and track your progress.

Sign in free to continue this lesson
Pass the quiz above to chart this quest in your Journal.

Sources

/guides/sug-using-print-for-verse-debugging
Source

Biloxi Studios original lesson

Guided course

Add this lesson to your free study plan.

🧭 The Keeper’s log

Quest complete? Chart your next heading from the πŸ¦‘ West Coves expedition.

β›΅ Take me there