
Debugging in Verse: Print Plus On-Screen HUD Widgets
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}")logs2 + 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 anif:if (UI := Player.GetPlayerUI[]):.- Build a
canvaswhose slot holds atext_block, then callUI.AddWidget(Canvas). - Keep a reference to the
text_blockand call.SetText(...)to update it live.SetTexttakes amessage, 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.
Check your understanding
Test yourself with an interactive quiz and track your progress + earn XP — free for members.
Turn this into a guided course
Add Using Print() for Verse Debugging 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.
Original tutorial generated by Verse Island from the Verse/UEFN knowledge base, with references to the Epic Games sources above. Code is validated against the knowledge base.