Skip to content

UMageItCombatTextSubsystem

Base Class: ULocalPlayerSubsystem

UMageItCombatTextSubsystem is the single entry point for spawning combat text. Being a ULocalPlayerSubsystem, it is automatically instantiated per local player, making it highly efficient and easy to access without manual initialization.

It owns a map of renderer instances (ActiveRenderers), keyed by FGameplayTag, and is responsible for resolving which renderer should handle a given event, initializing it (lazily by default, or eagerly for renderers opted into bInitializeAtBeginPlay), and shutting all of them down when the player is deinitialized.

Right-click anywhere in an Event Graph and search for Get MageItCombatTextSubsystem.

if (APlayerController* PC = GetWorld()->GetFirstPlayerController())
{
if (ULocalPlayer* LocalPlayer = PC->GetLocalPlayer())
{
UMageItCombatTextSubsystem* CombatTextSubsystem = LocalPlayer->GetSubsystem<UMageItCombatTextSubsystem>();
}
}
  • ActiveRenderers (Map<GameplayTag, UMageItCombatTextRendererBase*>, BlueprintReadOnly): Renderer instances created so far, keyed by the leaf FGameplayTag that first requested them.

virtual void Initialize(FSubsystemCollectionBase& Collection) override;

Called automatically by the engine when the local player subsystem is created. Reads UMageItCombatTextSettings::RendererRegistry and calls GetRenderer up front for every entry whose bInitializeAtBeginPlay is true, warming those renderers up immediately instead of waiting for their first damage event. All other entries remain lazy.

UMageItCombatTextRendererBase* GetRenderer(const FGameplayTag DamageTag);

(Blueprint Callable) Lazily loads and initializes the renderer for DamageTag, returning the cached instance on subsequent calls.

Resolution order:

  1. Look up DamageTag directly in ActiveRenderers. Return immediately if found.
  2. Otherwise, read UMageItCombatTextSettings::RendererRegistry and walk up the tag hierarchy — DamageTag, then DamageTag.RequestDirectParent(), and so on — until an entry with a non-null RendererClass is found.
  3. Synchronously load the resolved RendererClass, construct a new renderer instance (NewObject), call Initialize on it, and cache it in ActiveRenderers under the original leaf tag (not the ancestor tag that resolved the class), so repeated lookups for that exact leaf tag are O(1).
  4. Returns nullptr if no tag anywhere up the hierarchy has a registered renderer class.
void AddDamageEvent(const FMageItCombatTextEvent& Event);

(Blueprint Callable) Resolves the renderer for Event.DamageTag via GetRenderer and forwards the event to its RenderDamage. If no renderer resolves, logs a Warning to the LogMageitCombatText category and drops the event.

virtual void Deinitialize() override;

Calls Shutdown() on every active renderer and empties ActiveRenderers. Called automatically by the engine when the local player subsystem is torn down.