Build a Real-Time Countdown Timer in Verse
What you'll learn
By the end of this guide you will be able to:
- Create a
canvasand atext_blockwidget in Verse. - Attach that UI to a player with
GetPlayerUI[...]andAddWidget. - Drive a countdown with a
loopandSleep. - Refresh the on-screen text every second by rebuilding the widget content.
How it works
UI in Verse is built from widgets that live inside a player's player_ui. The key APIs from the live digest are:
GetPlayerUI[Player]— a<decides>function (note the[]brackets). It fails if the player has no UI, so you must call it inside a failure context such as anif.PlayerUI.AddWidget(Widget)— attaches a widget to the screen. This one is a normal call with().Sleep(Seconds)— a<suspends>function that pauses the coroutine. Because weawaittime, our timer must run insideOnBegin<override>()<suspends>.
The important subtlety: a text_block's text is set when the widget is constructed. To make the number change every second we keep a RemainingTime variable, then rebuild the widget's text using a binding so the same on-screen widget re-reads our value. We use a []player list of the widgets/bindings so we can update every player's screen.
The simplest robust pattern (and the one below) is: create ONE text_block per player whose Text reads a message we regenerate, and re-set it each tick. Verse text_block accepts a message for its Text field, and we build that message with string interpolation — never string + concatenation.
Let's build it
This device counts down from TotalTime seconds, showing the remaining whole seconds on the HUD of every player in the playspace and updating once per second.
using { /Fortnite.com/Devices }
using { /Fortnite.com/UI }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Simulation }
using { /Verse.org/Colors }
# A real-time countdown timer that renders on every player's screen.
countdown_timer_device := class<concrete>(creative_device):
# How long the countdown lasts, in seconds. Editable in UEFN.
@editable
TotalTime : int = 10
# Seconds left. We rebuild the text from this each tick.
var RemainingTime : int = 0
# Entry point. <suspends> is required because Sleep awaits time.
OnBegin<override>()<suspends>: void =
set RemainingTime = TotalTime
# Build one text widget per player and attach it to their UI.
# We keep each player's widget so we can refresh its text later.
var Widgets : []text_block = array{}
for (Player : GetPlayspace().GetPlayers()):
# GetPlayerUI is <decides> -> call with [] inside the if.
if (PUI := GetPlayerUI[Player]):
TimeText := text_block:
DefaultTextColor := NamedColors.White
DefaultText := MakeCountdownMessage(RemainingTime)
# AddWidget is a normal () call, not fallible.
PUI.AddWidget(TimeText)
set Widgets += array{TimeText}
# Drive the countdown: one tick per second until we hit zero.
loop:
Sleep(1.0)
set RemainingTime = RemainingTime - 1
# Refresh every player's on-screen text.
for (W : Widgets):
W.SetText(MakeCountdownMessage(RemainingTime))
if (RemainingTime <= 0):
break
# Build the display text with interpolation (never string '+').
MakeCountdownMessage(Seconds : int) : message =
StringToMessage("Time Remaining: {Seconds}")
# Wrap a string as a message for text_block APIs.
StringToMessage<localizes>(String : string) : message = "{String}"
Note:
text_blocksets its content throughDefaultText/SetText, which take amessage. Because you cannot+astringonto amessage, we build the whole line with interpolation insideStringToMessage, a<localizes>helper that turns a plain string into amessage.
Try it yourself
- Place the device in your level and drop the Verse script onto it.
- Set
TotalTimein the device's Details panel to any duration you like. - Play the session — every player should see the number tick down once per second.
- Extend it: fire a trigger or end the round when
RemainingTimehits0, or changeDefaultTextColortoNamedColors.Redfor the final few seconds by constructing a second widget. - Late-joiner exercise: subscribe to a player-added event and call
GetPlayerUI[NewPlayer]+AddWidgetfor players who join mid-countdown.
Recap
GetPlayerUI[Player]is fallible (<decides>) — always call it with[]inside anif/forcondition.AddWidget(...)andSleep(...)are ordinary()calls;Sleepneeds a<suspends>context, whichOnBeginprovides.- A
text_blockshows amessage; build text with interpolation, neverstring + message. - Keep a variable (
RemainingTime) as the source of truth and re-set the widget's text each tick to make the display update in real time. - Reassign mutables with
set(set RemainingTime = RemainingTime - 1) — there is no-=or--in Verse.
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 Implementing a Real-Time Countdown Timer with UI Text Binding 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.