Lesson 9 gave you BP_MissionDirector with dispatchers and phase logic. This lesson finally lets the player see that truth: objective text, detection or suspicion, and setback cues that use the same numbers the AI reads—not a second, drifting copy.

Lesson objective
By the end of this lesson you will have:
- A
WBP_StealthHUD(or nested widgets) added to the viewport from your player controller or pawn on begin play. - Bindings from
BP_MissionDirectorevents to objective lines and optional secondary state. - A detection meter (progress bar, material parameter, or simple fill) driven from one replicated-friendly value (stimulus, alert tier, or custom 0–1) that ramps with suspicion and drops on cooldown—matching Lesson 5–7 tuning.
Step 1: Confirm the single source of truth
Before placing widgets, list what the HUD may never invent on its own:
| UI element | Authoritative source |
|---|---|
| Primary / secondary text | BP_MissionDirector (or subsystem you used in Lesson 9) |
| Mission phase / setback banner | Same director |
| Detection fill | Perception interface, alert enum, or custom float you already log for AI |
If you duplicate “suspicion” in the widget with a second timeline, you will ship lies (“HUD says clear, guard is hunting”). Read the same variable or event the Behavior Tree uses for search or engaged.
Step 2: Create the HUD widget
- Add User Widget
WBP_StealthHUD. - Root with a canvas or overlay; pin safe zones (anchors inset ~4–6% from edges) for TV and ultrawide crops.
- Minimum blocks:
- ObjectiveTitle (Text)
- ObjectiveBody (Text, smaller)
- DetectionBar (Progress Bar)
- StateBanner (Text, optional—for Setback, Detected, Checkpoint)
Pro tip: keep fonts to two weights; stealth readability beats decoration.
Step 3: Spawn the HUD once
In BP_StealthPlayerController (or your controller of choice):
- On BeginPlay, Get Actor of Class →
BP_MissionDirector→ store reference. - Create Widget
WBP_StealthHUD→ Add to Viewport (Z-order above world, below pause menu). - Pass MissionDirector reference to the widget (expose variable on widget, set right after create).
If you use multiple local players later, gate create with Is Locally Controlled checks.
Step 4: Bind objective dispatchers
On WBP_StealthHUD Event Construct (or a custom Initialize event):
- Bind to
OnObjectiveChanged(or the custom events you added in Lesson 9). - On fire, set ObjectiveTitle / ObjectiveBody from payload (struct, tags, or parallel string vars on the director).
- When primary completes, optionally pulse opacity or play a short animation—under 0.3 s so it does not mask gameplay.
If you did not add dispatchers yet, add them now on BP_MissionDirector and call them from RegisterPrimaryComplete, ApplySetback, etc.
Step 5: Drive the detection meter
Pick one pipeline that matches your Lesson 5–7 setup:
- Option A — Stimulus magnitude: map hearing + sight contributions to a 0–1 float each tick or on perception update; lerp the bar toward that target.
- Option B — Alert enum: Idle = 0, Suspicious = 0.33, Investigate = 0.66, Engaged = 1.0 with lerp down on lost sight timers.
Expose SetDetectionNormalized(float) on the widget. The player or a small UI bridge Blueprint reads perception from the focused guard or an aggregated “worst case” value—whatever you documented in Lesson 7.
Critical: clamp and smooth. Raw perception spikes every frame look like broken UI.
Step 6: Accessibility and contrast
Stealth games fail players when red = danger is the only channel.
- Add a secondary cue: icon, thickness, or pulse rate on the bar—not color alone.
- Test ObjectiveBody on snow and cave shots; add a thin dark plate behind text if needed.
- Offer a
UI_HighContrastbool on the director or settings save; swap text and bar styles (higher stroke, simpler gradients).
Our accessibility plugins and checklists resource is engine-mixed but the rubric (contrast, motion, remapping) still applies to UMG planning.
Step 7: Pause, death, and setback layering
- When pause opens, remove or hide gameplay HUD—or lower opacity so menu reads first.
- Setback (Lesson 9) should trigger a short banner + optional bar flash using the same
ApplySetbackpath—no duplicate timer in the widget.
Mini challenge
- Force primary complete in PIE—confirm title updates once (no double bind).
- Walk into sight until investigate—bar should rise and fall on cooldown with no desync versus guard anim.
- Trigger checkpoint—HUD should not reset objective text unless the director fires a refresh event.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Bar stuck at full | No decay / wrong enum | Add lerp to zero on lost contact; verify update path |
| Objectives blank | Director not found | Delay bind one tick; validate reference on HUD construct |
| Double text updates | Bound twice | Unbind before rebind or guard with bool |
| Widget ignores input | Focus / hit test | Disable hit testing on HUD root if clicks should pass through |
Summary
- One authority for mission strings; one pipeline for threat readout.
- UMG is view—not a second game loop.
- Accessibility is layout + motion, not a post-launch patch.
Further reading
- Unreal UMG widgets guide – layout and input modes.
- Combat feel and juice resources – timing feedback without camera abuse.
FAQ
Widget in world space for diegetic UI?
Possible for markers; for slice scope, screen HUD is faster to ship.
Multiplayer?
Replicate director phase and detection tier on server; HUD reads replicated vars.
Next: Lesson 11: Audio Stealth Mix and Spatial Cues covers footsteps, occlusion, and stingers tied to alert changes. Finish Lesson 10 when your HUD survives a five-minute PIE session with no stale objective text after checkpoint restore.