UMG Widgets with Verse Custom Data Fields

In this lesson you'll learn to

  • βœ“Student can build a UMG widget blueprint with custom data fields and drive them live from Verse (data binding), the newest UI workflow.

Student can build a UMG widget blueprint with custom data fields and drive them live from Verse (data binding), the newest UI workflow.

πŸ“– Reference & full walkthrough: UMG Widgets with Verse Custom Data Fields

πŸ” Builds on: north-jungle UI widgets; east-volcano data layers

🧩 Your capstone piece: The dive-round scoreboard + oxygen meter UMG overlay driven by Verse data fields


The Deeps are where the training wheels come off. Back in Barnaby's jungle you drew your first HUD entirely in Verse β€” a canvas, a couple of text_blocks, pushed to the screen with GetPlayerUI[] (the First Verse UI: Lap Counter HUD and Canvas Layout lessons). That workflow is still great for quick overlays, but it has a ceiling: everything is styled in code, and your artists can't touch it. The newest UEFN UI workflow flips the arrangement. You design the widget in UMG β€” Unreal Motion Graphics, the full widget-blueprint editor β€” give it custom data fields through a Viewmodel, and then drive those fields live from Verse. Designers own the pixels; Verse owns the numbers. This lesson wires up both halves.

What you will build

The Deeps capstone piece for this lesson: the dive-round scoreboard + oxygen meter UMG overlay, driven by Verse data fields. One widget blueprint shows two live readouts:

  • RELICS BANKED β€” a scoreboard text field that jumps every time a diver banks a relic.
  • OXYGEN β€” a progress bar that drains second by second while the dive round runs.

Neither number lives in the widget. Both live in Verse, carried by two tracker_devices whose data fields (Value, Target, Title Text, Description Text) the widget binds to through the Device – Tracker View Model. This is the same one-device-owns-the-data pattern you built in Cinder's volcano (Live Scoreboard on the Cannon Wall and End-of-Round Leaderboard from a Map β€” the east-volcano data layers): gameplay code writes to one authoritative data owner, and every display surface just renders it. The only thing that changes today is the display surface β€” a designer-built UMG widget instead of a Verse-drawn canvas.

Walkthrough

Step 1 β€” Build the widget blueprint in UMG

  1. In UEFN's Content Browser, right-click β†’ User Interface β†’ Widget Blueprint. Name it WBP_DiveHUD.
  2. In the designer, add a Text Block for the scoreboard (this will show RELICS BANKED and the number) and a Progress Bar for the oxygen meter. Style them however the deep demands β€” fonts, materials, glow. Verse never sees any of this.
  3. Open Window β†’ Viewmodels, click + Viewmodel, and add Device – Tracker View Model. Add it twice β€” one viewmodel per tracker (score and oxygen). These viewmodels are what expose the tracker's custom data fields (Value, Target, Title Text, Description Text) to the widget.
  4. In View Bindings, bind the score Text Block's text to the score viewmodel's Value (use the To Text (Integer) conversion function), and bind the Progress Bar's Percent to the oxygen viewmodel using the conversion that divides Value by Target. That division is why Verse must set a sensible Target β€” the bar math depends on it.

Step 2 β€” Host the widget on screen

Custom user widgets reach the player's screen through the HUD Controller device. Place one, add WBP_DiveHUD to its custom widget slot, and while you're there switch off the default Fortnite HUD elements your overlay replaces. (You met this device in the Making a Custom HUD flow; it's the frame your widget hangs in.)

Step 3 β€” Place the data-field carriers

Place two Tracker devices (score + oxygen) and one Trigger device (the relic-banking pressure plate from Pressure Plates of the Athenaeum). The trackers don't need Show on HUD β€” your UMG widget is their display now. They exist purely as the data fields your widget binds to and your Verse writes to.

Step 4 β€” Drive the data fields from Verse

Here is the complete device. Wire ScoreTracker, OxygenTracker, and RelicTrigger in the Details panel after dragging it onto the island.

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

# Drives the dive-round scoreboard + oxygen meter UMG overlay.
# The widget blueprint binds to the two trackers' data fields;
# THIS device owns every value those fields display.
dive_hud_data_device := class(creative_device):

    # Bound in the widget as the RELICS BANKED scoreboard field.
    @editable
    ScoreTracker : tracker_device = tracker_device{}

    # Bound in the widget as the oxygen progress bar (Value / Target).
    @editable
    OxygenTracker : tracker_device = tracker_device{}

    # Divers step on this to bank a relic (Pressure Plates lesson).
    @editable
    RelicTrigger : trigger_device = trigger_device{}

    @editable
    DiveSeconds : int = 90

    @editable
    RelicValue : int = 25

    ScoreTitle<localizes> : message = "RELICS BANKED"
    OxygenTitle<localizes> : message = "OXYGEN"
    LowAirWarning<localizes> : message = "Surface soon, diver!"

    var OxygenRemaining : int = 0

    OnBegin<override>()<suspends>:void =
        # Hand every player both data-field carriers.
        ScoreTracker.AssignToAll()
        OxygenTracker.AssignToAll()

        # Verse sets the widget-facing fields: titles first...
        ScoreTracker.SetTitleText(ScoreTitle)
        OxygenTracker.SetTitleText(OxygenTitle)

        # ...then the numbers the progress-bar math depends on.
        set OxygenRemaining = DiveSeconds
        OxygenTracker.SetTarget(DiveSeconds)
        OxygenTracker.SetValue(DiveSeconds)

        # Relic banking is event-driven (Events Over Polling lesson).
        RelicTrigger.TriggeredEvent.Subscribe(OnRelicBanked)

        # The oxygen drain: one write per second, the widget follows live.
        loop:
            Sleep(1.0)
            set OxygenRemaining = OxygenRemaining - 1
            OxygenTracker.SetValue(OxygenRemaining)
            if (OxygenRemaining = 10):
                OxygenTracker.SetDescriptionText(LowAirWarning)
            if (OxygenRemaining <= 0):
                break
        Print("Dive round over. Everyone to the surface!")

    # A diver banked a relic: Verse updates the score field, and the
    # widget's bound text block repaints on its own.
    OnRelicBanked(MaybeAgent : ?agent):void =
        if (BankingAgent := MaybeAgent?):
            NewScore := ScoreTracker.GetValue(BankingAgent) + RelicValue
            ScoreTracker.SetValue(BankingAgent, NewScore)

What to notice

Line Why it matters
AssignToAll() A tracker only carries data for agents it's assigned to. Assign first, write second.
SetTarget(DiveSeconds) then SetValue(DiveSeconds) The widget's progress-bar binding computes Value / Target. Set both, in this order, before the drain starts, or the bar renders garbage for a frame.
SetValue(OxygenRemaining) in the loop One Verse write per second. No widget code runs β€” the binding repaints because the data field changed. This is data binding: writes on one side, paint on the other.
SetValue(BankingAgent, NewScore) The per-agent overload. Each diver's scoreboard shows their banked total β€” same widget blueprint, different data per player.
SetDescriptionText(LowAirWarning) Even flavour text is a data field. The widget can bind Description Text to a warning label that only appears when non-empty.

The division of labour is total: the widget blueprint never computes, and the Verse device never styles. If your scoreboard ever shows a stale number, you know exactly which side to debug β€” the side that owns the value. That's Verse, always.

Common patterns

Team oxygen pools β€” the SetValue(TeamIndex, ...) overload

tracker_device.SetValue has three overloads: everyone, one team, one agent. A divers-vs-wardens round (you built the teams in Divers vs Wardens) can give each team its own shared air supply with one line per team:

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }

team_oxygen_device := class(creative_device):

    @editable
    TeamOxygen : tracker_device = tracker_device{}

    OnBegin<override>()<suspends>:void =
        TeamOxygen.AssignToAll()
        TeamOxygen.SetTarget(120)
        # Team 0 is already mid-dive; team 1 starts topside with full air.
        TeamOxygen.SetValue(0, 60)
        TeamOxygen.SetValue(1, 120)

With the tracker's Sharing option set to Team, every teammate's widget binds to the same team-owned value β€” one write updates the whole squad's HUD.

Reacting when a data field hits its target

Because the tracker knows both Value and Target, it fires CompleteEvent the moment a diver's score reaches the quota β€” no polling loop needed:

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

dive_goal_device := class(creative_device):

    @editable
    ScoreTracker : tracker_device = tracker_device{}

    GoalTitle<localizes> : message = "RELIC QUOTA"

    OnBegin<override>()<suspends>:void =
        ScoreTracker.AssignToAll()
        ScoreTracker.SetTitleText(GoalTitle)
        ScoreTracker.SetTarget(100)
        ScoreTracker.CompleteEvent.Subscribe(OnQuotaReached)

    OnQuotaReached(Winner : agent):void =
        Print("A diver hit the relic quota!")

Where this goes next

This overlay is a load-bearing wall of CAPSTONE: Athenaeum Depths. The Sunken Dive Round project imports dive_hud_data_device as-is β€” its round state machine calls SetValue on the oxygen tracker instead of running its own drain loop, and the relic-banking triggers feed the score field. The capstone then layers on everything the rest of The Deeps teaches: the RelicLedger array drains into the scoreboard, detect_player_leave cleanup unassigns trackers when a diver disconnects, and the cinematic sequencer plays over your UMG overlay in the finale. Imports carried forward from earlier zones: north-jungle's UI-widget foundations (you'll still use GetPlayerUI[] canvases for quick debug overlays), and east-volcano's data-layer discipline β€” one owner per number, everywhere, always.

πŸ”’

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/umg-custom-data-fields
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 🌊 The Deeps expedition.

β›΅ Take me there