How-To: World-Space Indicators

Goal: float a widget over a world object (quest marker, nameplate, ping) with screen clamping and an off-screen arrow, using the pooled indicator pipeline.

Prerequisites
Quick Start done (the indicator layer lives in your HUD layout). A target actor with a USceneComponent to anchor to.

1. Put an indicator layer in the HUD

In BP_HUDLayout's Designer add a Crimson Indicator Layer (UCrimsonIndicatorLayer) filling the screen (e.g. in an Overlay slot, anchors Fill). Its ArrowBrush is the clamp-to-edge arrow sprite. The layer hosts and projects every indicator for the owning player.

2. Ensure the controller has the manager component

UCrimsonIndicatorManagerComponent (a UControllerComponent) owns the indicator list. Add it to your PlayerController: in Blueprint via Add Component -> Crimson Indicator Manager, in C++ via CreateDefaultSubobject, or let a GameFeature action inject it on the full stack. (CrimsonCore's UCrimsonCoreGameplayAbility_Interact creates one on demand for its default on-actor interaction prompt - manual setup is only needed when you drive indicators yourself.)

cpp
// PlayerController constructor
#include "IndicatorSystem/CrimsonIndicatorManagerComponent.h"
AMyPlayerController::AMyPlayerController(const FObjectInitializer& OI) : Super(OI)
{
IndicatorManager = CreateDefaultSubobject<UCrimsonIndicatorManagerComponent>(TEXT("IndicatorManager"));
}

3. Add an indicator

Node chain: Get Indicator Manager Component (from UCrimsonIndicatorLibrary, Controller = Get Player Controller) -> Construct Object From Class (class = Crimson Indicator Descriptor, outer = the manager) -> call its setters (Set Scene Component, Set Indicator Class, Set Clamp To Screen, Set Show Clamp To Screen Arrow) -> Add Indicator on the manager.

Placement setters beyond the basics: SetProjectionMode (ComponentPoint, ComponentBoundingBox, ComponentScreenBoundingBox, ActorBoundingBox, ActorScreenBoundingBox), SetComponentSocketName, SetHAlign/SetVAlign, SetWorldPositionOffset, SetScreenSpaceOffset, SetBoundingBoxAnchor, SetPriority, SetDesiredVisibility, SetAutoRemoveWhenIndicatorComponentIsNull (auto-cleanup when the target dies).

Verify
The widget tracks the target in PIE; walking it off-screen pins it to the edge with the arrow pointing at the target.

4. The indicator widget itself

Any UUserWidget works. Implement Crimson Indicator Widget Interface (ICrimsonIndicatorWidgetInterface) to receive lifecycle calls:

EventWhenDo
BindIndicator(Descriptor)Widget assigned to a descriptor (fresh or from the pool)Read GetDataObject / target and populate visuals.
UnbindIndicator(Descriptor)Widget returned to the poolClear every bound reference - the next bind may be a different target.

In Blueprint: open Class Settings -> Interfaces and add Crimson Indicator Widget Interface, then implement Event Bind Indicator (read the descriptor's Data Object and populate visuals) and Event Unbind Indicator (clear state).

Widgets are pooled by class
The layer reuses indicator widgets. State you do not clear in UnbindIndicator leaks into the next target that reuses the widget.

See also

  • How-To: Show a Context Menu - world-anchored menus use a different (focusable) mechanism.
  • Concept: Policy & Layout Architecture - where the indicator layer sits in the stack.