How-To: Show Pops on the HUD or a Health Bar

Goal: put combat text somewhere that is not the world - a fixed area of the screen, or attached to a UI widget such as a target frame or nameplate.

Prerequisites
You completed Quick Start and have a placement set assigned to your registry - see How-To: Position Pops, step 2.

1. Route a style to a fixed HUD area

Point a style's Placement Preset at one of the seeded screen rows (ScreenIncoming, ScreenOutgoing, ScreenNotification), or add your own Screen Anchor row. A screen anchor has two properties:

PropertyPurpose
ViewportAnchorNormalized position. (0,0) top-left, (0.5,0.5) center, (1,1) bottom-right
AnchorOffsetOffset from that anchor in layout units. Slate +Y is DOWN

Every pop routed there lands at the same place regardless of who was hit. Scrolling is not a separate feature - the motion preset already owns direction, distance and fan, so pair the area with whichever motion reads best.

Verify
Hit two different enemies at once with a style routed to ScreenNotification. Both pops appear in the same area and fan apart rather than stacking on one pixel.
Why they fan
A world placement groups its anti-overlap fan by anchor actor. A screen area has no actor, so it groups by the area's own PlacementId instead - otherwise every target would compete for the same pixel.

2. Make a UI widget addressable

To land pops on a health bar, that widget has to register an anchor id with UCrimsonCombatTextAnchorSubsystem. Anchor ids name your widgets, so the tag picker is deliberately unrestricted - use your own hierarchy. The plugin ships CrimsonCombatText.Anchor.TargetFrame and .Nameplate as examples only.

The zero-code path is the shipped Crimson Combat Text Anchor widget. It is a USizeBox, so it works as a real layout container - wrap your health bar to anchor to the bar's own geometry, or leave it empty with a fixed size as a pure point marker.

In your health bar widget Blueprint, drag a Crimson Combat Text Anchor (palette category Crimson) around the bar, and set its Anchor Id in the details panel. It registers and unregisters itself with the widget's lifetime - there is nothing to call.

For a per-enemy nameplate, also call Set Anchor Context Actor from the nameplate's init, passing the enemy. Every nameplate can then share one anchor id, and each pop resolves to the right one.

Verify
Open the dev tools Status tab in PIE. Your id appears under Registered widget anchors, marked [resolvable]. If it says [not painted], the widget exists but has never been drawn yet.

3. Route a style to the widget anchor

Add a Widget Anchor row to your placement set, give it a PlacementId, and set its AnchorId to the id your UI registered. Then point a style's Placement Preset at that row.

PropertyPurpose
AnchorIdThe id your UI registered under
bUseTargetActorContextLook up the pop's target actor first, so per-enemy nameplates each get their own. Falls back to the global registration either way
WidgetAlignmentPoint on the widget. (0.5,0) top-center, (0.5,0.5) center, (0.5,1) bottom-center
AnchorOffsetOffset from that point, in layout units
bHideWhenAnchorLostThe bar was hidden or destroyed mid-flight: hide the pop, or freeze it where it was
Verify
Damage the actor whose bar carries the anchor. Its numbers appear on the bar. Hide the bar and they hide or freeze, according to bHideWhenAnchorLost.

4. Give it a fallback

A widget anchor cannot always resolve. The bar may be hidden, destroyed, or simply never painted - a widget's geometry is zero-sized until its first paint, and the plugin refuses to treat that as a real position rather than dropping pops in the corner of the screen.

When a placement declines a pop, the subsystem walks its Fallback chain (up to four deep) and discards the pop only if every link declines. Set Fallback on your Widget Anchor row to a World Actor placement and unresolvable pops quietly revert to appearing over the enemy.

No fallback means no pop
A Widget Anchor with an empty Fallback discards text whenever its widget is unavailable. That is legitimate for genuinely UI-only feedback, but it is rarely what you want for damage numbers.
Verify
Fire a pop at an actor before its health bar has ever been shown. With a fallback it appears over the actor; without one it does not appear at all, and the log carries a no placement accepted this pop warning.

Multiplayer

Placement is client-side and cosmetic only. Nothing here replicates, no placement runs on a dedicated server, and two players may resolve the same event to completely different places - which is exactly what per-player overrides rely on. The server's only involvement is the world location it puts on the event as a network fallback.

See also

  • How-To: Position Pops - placement sets and world anchoring.
  • How-To: Write Your Own Placement - custom placement logic in Blueprint or C++.
  • How-To: Expose Pop Options as User Settings - letting players re-route their own combat text.
  • How-To: Test Pops with the Dev Tools - the Status and Resolver tabs used to verify above.