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.
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.
Images/CrimsonUI/howto-indicator-layer.png2. 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.)
// PlayerController constructor#include "IndicatorSystem/CrimsonIndicatorManagerComponent.h"AMyPlayerController::AMyPlayerController(const FObjectInitializer& OI) : Super(OI){IndicatorManager = CreateDefaultSubobject<UCrimsonIndicatorManagerComponent>(TEXT("IndicatorManager"));}
3. Add an indicator
Images/CrimsonUI/howto-indicator-add-bp.pngGet the manager with Get Indicator Manager Component (from UCrimsonIndicatorLibrary). Create the descriptor with Construct Object From Class (class = Crimson Indicator Descriptor, outer = the manager), call its setters, then Add Indicator.
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).
4. The indicator widget itself
Any UUserWidget works. Implement Crimson Indicator Widget Interface (ICrimsonIndicatorWidgetInterface) to receive lifecycle calls:
| Event | When | Do |
|---|---|---|
BindIndicator(Descriptor) | Widget assigned to a descriptor (fresh or from the pool) | Read GetDataObject / target and populate visuals. |
UnbindIndicator(Descriptor) | Widget returned to the pool | Clear every bound reference - the next bind may be a different target. |
Images/CrimsonUI/howto-indicator-widget-bp.pngUnbindIndicator 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.