You have the logic that drains HP. Next you want a health bar in the top left so remaining health reads at a glance. That is what UE's UI creation feature, UMG (Unreal Motion Graphics) , is for.
In UMG you build a blueprint with text and bars arranged on it, then place an instance of it on screen during play. This article assembles, with one running example, show an HP bar in the top left → drain 25 per H press → update the display when HP changes .
What You'll Learn
- The difference between "creating" a Widget and "placing it on screen"
- What Designer and Graph do, and what anchors and containers do
- Converting HP into a 0-to-1 ratio and passing it to the bar
- Notifying HP changes, and applying the initial value when display starts
- A Widget takes two steps: create and place
- In the Designer, combine display elements and layout elements
- Anchors: what part of the screen you measure from
- Preparation: a character that has HP
- Hands-On 1: show an HP bar in the top left
- Hands-On 2: update the bar when HP changes
- Binding versus updating on change
- Checks when it does not work
- Bonus: cleaning up the HUD and expanding to other UI
- Summary
A Widget takes two steps: create and place
In other engines : this is Unity's uGUI / UI Toolkit and Godot's Control nodes . Building a screen as one asset and opening it later to overlay it is the same idea.
A Widget Blueprint is a blueprint, so saving the asset does not make it appear in the game. Displaying it takes two steps.

- Create Widget builds an instance from the blueprint.
- Add to Viewport places that instance in the game's display area.
Create Widget's Return Value is the instance you just made. Store it in a variable and you can later name that same HUD to update values or remove it from screen. That "value for naming the same thing later" is a reference .
Text and bars arranged inside a parent Widget display along with the parent. You do not call Add to Viewport per element.
In the Designer, combine display elements and layout elements
A Widget Blueprint has a Designer for building appearance and a Graph for building logic.

| Tab | What it decides | Our example |
|---|---|---|
| Designer | Element arrangement, size, color | Place "HP" and a bar in the top left |
| Graph | When and what to update | Receive new HP and change the bar length |
The Designer's Palette is the element store, and the Hierarchy is the parent-child relationship. Some elements show information , like Text and Progress Bar, and others decide where children go , like Canvas Panel and Horizontal Box.
A Canvas Panel lets you specify children's positions and sizes. A Horizontal Box arranges children left to right; a Vertical Box arranges them top to bottom. Here we put the HP group on a Canvas and arrange "HP" and the bar horizontally inside it.
Separating deciding the overall position from arranging within a group like this keeps adjustment manageable as you add elements.
Anchors: what part of the screen you measure from
Put the HP bar in the top left and you want it to stay there even when the screen gets wider. Anchors are that reference. They decide where in the parent Canvas Panel the position is measured from.
| Where you want it | Anchor | Examples |
|---|---|---|
| Top-left corner | Top left | HP, score |
| Top-right or bottom-right corner | The matching corner | Minimap, ammo count |
| Always centered | Center | Crosshair, confirm dialog |
| Filling the parent | Stretched on all four sides | Fade curtains, backgrounds |
The question to ask is "when the screen gets wider, where do I want this element to be?"
Anchors are set on the Slot of a direct child of a Canvas Panel. A Slot is the setting for how an element fits inside its parent. Selecting the bar inside the Horizontal Box will not show the Canvas anchors. Here we set them on the Horizontal Box placed directly on the Canvas.
Alignment decides which part of the element itself lines up with the position. (0, 0) is the element's top left; (0.5, 0.5) is its center. To center a dialog on a center anchor, set Alignment to (0.5, 0.5) as well.

Anchors are a position reference, not a single setting that handles every screen size. Text and padding sizes also involve DPI scaling, which scales the whole UI with resolution. Build the top-left layout first, then change the aspect ratio with the Designer's Screen Size to check.
Preparation: a character that has HP
We use a single-player Third Person Blueprint project . When creating a new one, choose None if the version offers Variants. Start from a state where WASD walks and Space jumps.
- Duplicate BP_ThirdPersonCharacter and name it
BP_HUDPractice. - Open the GameMode in use from the level's World Settings and change Default Pawn Class to BP_HUDPractice.
- Do not hand-place a character in the level; spawn from PlayerStart. Play and confirm the duplicated character moves.
Default Pawn Class is the character class spawned for the player. PlayerStart marks its spawn position.
In this exercise the character creates one HUD for itself. It passes a reference to itself into the HUD, so the HUD does not need a step that "searches for the controlled character". Managing HUDs across multiple players or respawns is considered separately at the end.
Create the following variables on BP_HUDPractice, compile, and set the defaults. Float is the numeric type that handles decimals.
| Variable | Type | Default | Role |
|---|---|---|---|
| MaxHealth | Float | 100 | Maximum HP |
| CurrentHealth | Float | 100 | Current HP |
We keep MaxHealth at 100 here. Since we later compute the ratio by division, keep max HP greater than 0. Do not make the variables Private, so the HUD can read the current values.

Hands-On 1: show an HP bar in the top left
1. Create the Widget Blueprint
Create "User Interface → Widget Blueprint" in the Content Browser, choosing User Widget if a parent class prompt appears. Name it WBP_PracticeHUD .
In the Designer, put a Canvas Panel at the root and add a Horizontal Box as its child. Inside the Horizontal Box, add a Text and a Progress Bar in that order.
Canvas Panel
└─ Horizontal Box (the HP group)
├─ Text (the letters HP)
└─ Progress Bar (HealthBar)
Select the Horizontal Box and set Slot (Canvas Panel Slot) to the following. Leave Size To Content off.
| Setting | Value |
|---|---|
| Anchors | Top left. Minimum and Maximum both (0, 0) |
| Position X / Y | 24 / 24 |
| Size X / Y | 320 / 32 |
| Alignment X / Y | 0 / 0 |
That places the HP display's top left 24 right and 24 down from the screen's top-left reference. The numbers are UI coordinate units; final pixel size depends on DPI scaling.
Set the Text content to "HP" and font size to 20. Set its Horizontal Box Slot Size to Auto, Vertical Alignment to Center, and Padding Right to 12. Auto means it uses the width the text needs; Padding is the gap to its neighbor.
Rename the Progress Bar to HealthBar and turn Is Variable on so the Graph can address it. Set its Horizontal Box Slot to Size = Fill, value 1, and Horizontal / Vertical Alignment = Fill. That gives the bar whatever the text and padding leave.
Set HealthBar's Percent to 1.0 , Bar Fill Type to Left to Right, and Fill Color and Opacity to a blue. Do not set a Bind on Percent. If the Designer shows "HP" and a full bar in the top left, the appearance is ready.

2. Create it from the character and place it on screen
In BP_HUDPractice's event graph, call Create Widget from BeginPlay. If BeginPlay already has work, continue at the end of its exec wire.
| Create Widget input | What to specify |
|---|---|
| Class | WBP_PracticeHUD |
| Owning Player | Get Player Controller's Return Value (Player Index = 0) |
Owning Player is the Player Controller of the player using this UI. Self here is the character, so pass Get Player Controller's result to Owning Player. Player Index = 0 designates our single player.
Right-click Create Widget's Return Value, choose Promote to Variable, and name it HUDRef . Its type becomes an Object Reference to WBP_PracticeHUD.
Wire the white exec line as Create Widget → Set HUDRef → Add to Viewport. Connect the stored HUDRef to Add to Viewport's Target.

Compile, save, and Play. If a full HP bar appears in the top left and WASD still moves you, this stage is done. It is a display-only HUD, so we add no Input Mode or mouse cursor settings.
3. Check by changing the aspect ratio
Return to WBP_PracticeHUD's Designer and switch Screen Size between 16:9 and 4:3. Confirm the HP display stays in the top left and the text and bar do not overlap.
If you want the bar's width to stretch with the screen, change the design so the Horizontal Box's left and right anchors spread, separately from pinning it top left. Here we use a fixed-width HP display that stays grouped in the top left.
Hands-On 2: update the bar when HP changes
So far the bar is appearance only. Next, have the character announce "HP changed" and the HUD receive it and change the length.
The mechanism for that notification is an Event Dispatcher . Register the work you want to receive with Bind , and when the notifying side calls Call , the registered work runs. Basic wiring is also covered in Event Dispatcher Basics.

1. Drain 25 HP and notify
Add an Event Dispatcher in BP_HUDPractice's My Blueprint and name it OnPracticeHealthChanged . Add Float inputs Current and Maximum . Those two pass "what it is now, and what full is".
Next create a function ReducePracticeHealth . We drain 25 at a time for testing, so the function needs no inputs.
- Subtract 25 from CurrentHealth.
- Connect to Clamp (Float) with Min = 0 and Max = MaxHealth.
- Feed Clamp's result into Set CurrentHealth.
- From Set CurrentHealth's exec output, Call OnPracticeHealthChanged.
- Pass the updated CurrentHealth to Current and MaxHealth to Maximum.

Clamp keeps a value within a range. Subtracting 25 from an HP of 10 stops at 0. Call the notification after writing HP.

Create an Input Action IA_HUDDamage as Digital (Bool) with no Modifiers or Triggers. Add it to the Input Mapping Context used for template movement (IMC_Default or similar) and assign the H key. Leave the existing movement and look bindings in place.
Place IA_HUDDamage in BP_HUDPractice's event graph and call ReducePracticeHealth from Started. If working with input assets is unfamiliar, see Enhanced Input Basics.

Nothing connects to the HUD yet, so the bar does not move at this point. Place a Print String after the Call and display CurrentHealth. If the first H press shows 75, then 50 → 25 → 0, the HP-draining logic works. You can remove that Print String afterwards.
2. Build a function on the HUD that displays the ratio
Move to WBP_PracticeHUD's Graph and create a function RefreshPracticeHealth with Float inputs Current and Maximum, and no outputs.
The Percent you pass to the bar is a ratio where 0 is empty and 1 is full. With HP 75 and max HP 100, pass 75 ÷ 100 = 0.75 . It is not a value you pass 75 into directly.
Compute Current ÷ Maximum with Divide and pass the result through Clamp (Float) between 0 and 1. Place HealthBar with Get and create Set Percent from it. Target is HealthBar and In Percent is Clamp's result. Connect the function entry's white exec output to Set Percent.

Now pass that division result to the bar.

Max HP uses the positive 100 we set in preparation. If you extend this to a game where max HP can change, keep the value positive wherever it is set so you never divide by zero.
3. Tell the created HUD who to display
Create a function InitializePracticeHUD in WBP_PracticeHUD with an input Source typed as an Object Reference to BP_HUDPractice . Source is the character instance whose HP this HUD displays.
Compile, then drag from Source and create Bind Event to OnPracticeHealthChanged with Source as Target. From the red Event pin create a Create Event, set Object = self, and choose RefreshPracticeHealth in Select Function.
Create Event here is not the same as Create Widget. It builds the specification "make this HUD's RefreshPracticeHealth the receiver of the notification" . The function appears as a candidate when its input types and count match the Dispatcher.

Connect InitializePracticeHUD's white output to Bind Event, and place a call to RefreshPracticeHealth after it. That call's Target is self, and Current and Maximum receive CurrentHealth and MaxHealth read from Source.

Drag from Source's blue pin and search for Get CurrentHealth and Get MaxHealth to read that character's values. Connect the green outputs to RefreshPracticeHealth's Current and Maximum.

Bind registers you for future notifications. It does not tell you about HP changes that happened before registration. So right after registering, read the current values and match the display once. That is applying the initial value.
4. Call the initialization before displaying
Return to BP_HUDPractice. Between Set HUDRef and Add to Viewport, insert InitializePracticeHUD with HUDRef as Target. Pass Self to Source.
The final order is Create Widget → store in HUDRef → InitializePracticeHUD → Add to Viewport. Since we keep using the same HUD, there is no need for a second Create Widget or Add to Viewport.

In that order you explicitly name who the HUD displays, register for notifications, apply the current value, and then place it on screen. We do not add logic to WBP_PracticeHUD's Event Construct that searches for the player.
5. Compare the moment it drains with the value at display start
Play, click the screen, and press H one press at a time. If it reads 75 percent after one, 50 after two, 25 after three, and empty after four, HP changes are reaching the bar. Holding the key still only fires Started once, so release and press again.

The diagram shows the bar in four segments so the ratio is easy to compare. The HealthBar you build is one continuous bar, and the character is the Third Person template's.
Try the initial value too. Set only the Designer's HealthBar Percent to 0.25 and Play with the character's CurrentHealth still at 100. In game it should be full , because the Designer's sample value was updated with the game's current HP.
Next, temporarily disconnect only the final RefreshPracticeHealth call inside InitializePracticeHUD from the exec wire. Leave the Bind. Right after Play it stays at 25 percent, but pressing H delivers the HP 75 notification and it becomes 75 percent. That shows "logic that shows the right thing from the start" and "logic that updates on change" are separate. Restore the exec wire and the Designer Percent of 1.0 afterwards.

The percentages in the diagram are how full the bar looks on screen. Removing the initial application does not mean the character's HP dropped to 25.
Binding versus updating on change
UMG also offers Binding , which ties values like Percent to a function or variable. The display side reads the value repeatedly, which is quick to wire in a short prototype.
Our approach instead sends a notification from the logic that changed HP, and the HUD calls Set Percent. The HUD does not have to keep asking about HP while nothing changes. For displays like HP or score where you know where the value changes, making this the default keeps update triggers easy to trace.

Do not manage the same Percent with both a Binding and Set Percent. A direct Set breaks the Binding, so thinking "the Binding always overwrites the Set" will mislead you about the behavior. When switching away from an existing Binding, clear the assignment from Percent's Bind menu in the Designer so the update method is consistent.
Event Dispatchers are not mandatory. If a parent Widget only updates its own child bar, calling Set Percent directly is fine. The point of a notification is that the character does not need to know the bar's layout or element names to pass along "HP changed".
Checks when it does not work
Rather than chasing everything at once, split it into display logic → HP drain logic → notification → bar update .
| Symptom | Where to check |
|---|---|
| The HP display does not appear | Default Pawn Class, BeginPlay's exec wire, Create Widget's Class, Add to Viewport's Target |
| Only the bar is invisible | The Horizontal Box's width and height, HealthBar's Fill, Percent, and color opacity |
| Pressing H does not drain HP | Whether H is registered in an active IMC, and whether Started calls the function |
| HP drains but the bar does not move | The InitializePracticeHUD call, Source = Self, and Bind's Target and Event |
| RefreshPracticeHealth is not a candidate | Whether it has two Float inputs and no outputs, and whether you compiled |
| It always looks full | Whether you pass current HP ÷ max HP instead of putting 75 straight into Set Percent |
| Only the first display is wrong | Whether there is a call passing current values right after Bind |
If you are unsure the notification arrives, temporarily place a Print String at RefreshPracticeHealth's entry. If it fires when you press H, the next things to check are HealthBar's Target and the ratio.
Bonus: cleaning up the HUD and expanding to other UI
A HUD whose life ends with the character
The HUD here was made for one character. From BP_HUDPractice's Event EndPlay, connect to Is Valid (the version with a white exec pin) and feed HUDRef into Input Object. From the valid branch call Remove from Parent with HUDRef as Target, and the HUD leaves the screen when that character is done.

Remove from Parent detaches from the display hierarchy. It does not mean the Widget itself is destroyed at that instant. In setups where you remove only the HUD from a living character, or reuse the same HUD, also decide when to unbind the notification. For unbinding with the same target and receiver via Unbind, see Event Dispatcher Basics.
Also, Event Construct can be called again when the display hierarchy is rebuilt. Our initialization is called explicitly once by the creator. Do not mix it with logic that re-registers the notification on every display.
HUDs that survive respawn, and menus you operate
To keep the HUD across respawns, consider managing it on something like the Player Controller and switching its display target to the new character. Keeping the HUD and re-pointing it at the new HP owner are separate tasks.
Where to put game state leads to Game Framework Basics, and HP bars floating above heads lead to the Widget Component article.
To move on to a pause screen with pressable buttons, the pause menu article combines stopping the game with routing input to the UI. First get comfortable checking display and data updates separately with this HUD.
Summary
Build appearance in a Widget Blueprint, create an instance with Create Widget, and place it on screen with Add to Viewport. For an HP bar, add "convert current HP into a ratio and pass it" to that display flow.
Once you have "apply the current value first, then update on change notifications", you can apply the same to score and ammo displays. Finish the version where H shrinks the bar, then try swapping in the attack logic from the health and damage article.
Reference: Create Widget, UMG anchors, Property Binding, Driving UI updates with events, UMG optimization guidelines.
To translate and switch on-screen text, Localization Dashboard is the entry point; to show another camera's view in the UI, try building a minimap with a Render Target.