Skip to content

Configuring Renderers

MageIt Combat Text uses a GameplayTag-driven registry to decide which renderer handles which damage event. This gives you full control over the cost/flexibility tradeoff — cheap, high-volume chip damage can go through Niagara, while rare critical hits or boss telegraphs can go through the more flexible UMG renderer.


🏷️ 1. The Renderer Registry (Project Settings)

Section titled “🏷️ 1. The Renderer Registry (Project Settings)”

The registry lives on UMageItCombatTextSettings, a UDeveloperSettings class.

  1. On the top menu bar of the Unreal Editor, click Edit.
  2. Select Project Settings.
  3. Scroll down the left-hand panel until you find the Plugins category.
  4. Click on Combat Text.
  5. Add entries to the Renderer Registry map: a FGameplayTag key, and an FMageItCombatTextRendererEntry value with two fields — Renderer Class (a soft class reference) and b Initialize At Begin Play (unchecked by default — see the tip below).

You don’t need an entry for every leaf tag. UMageItCombatTextSubsystem::GetRenderer walks up the tag hierarchy using RequestDirectParent() until it finds a registered class:

Damage.Fire.Critical -> Damage.Fire -> Damage

Register broad tags for your defaults (e.g. Damage), then add more specific tags only where a damage type needs a different renderer (e.g. Damage.Fire.Critical -> a flashier UMG renderer for crits).


Use CaseRecommended Renderer
Rich, designer-authored widget animationsUMG
Damage that should accumulate visually per-targetUMG
Hundreds of numbers on screen simultaneouslyNiagara
Stylized text as SDF sprites/lettersNiagara
Simple pop/float/fade numbers with no widget costSlate

Each damage type gets its own renderer instance, lazily created the first time a tag needs it and cached for the lifetime of the local player. This means a game that never routes an event to the Niagara renderer never pays the cost of spawning its Niagara system.


The most commonly tuned properties on UMageItCombatTextRendererUMG:

  • WidgetClass: Your UMageItCombatTextWidget subclass.
  • PoolSize: Widgets pre-allocated at Initialize. Set this to your realistic peak concurrent damage numbers.
  • MaxPoolSize: Optional hard ceiling the pool may grow to when exhausted, instead of dropping events. 0 means unbounded growth.
  • LocationInterpSpeed: How quickly the widget’s tracked world position catches up to a moving target.
  • bTrackActorLocation / bUpdateLocation / bSmoothLocationUpdate: Control whether and how smoothly the number follows its target actor as it moves.

The most commonly tuned properties on UMageItCombatTextRendererNiagara:

  • MasterSystemAsset: The Niagara System that reads the User.DamageInfo / User.DamageStyle arrays this renderer writes to every tick.
  • DigitSize / DigitSpacing: Controls the on-screen size of each digit sprite and the horizontal spacing between digits in a multi-digit number.
  • DefaultTextColor / OutlineColor / SpriteMaterial: Forwarded to the Niagara system as user parameters at Initialize.

Override FindDamageStyle, FindScale, or FindSpriteIndex in a Blueprint child class to drive per-event styling (e.g. a different style index for critical hits, or a larger scale for high damage values) without touching C++.


The most commonly tuned properties on UMageItCombatTextRendererSlate:

  • TextFont / TextColor / ShadowColor / ShadowOffset: Basic text appearance.
  • DefaultAnimationDuration: How long the built-in pop/float/fade animation runs.
  • VelocityHalfConeAngle, MinVelocity, MaxVelocity: Randomizes the lateral drift direction and speed of each spawned number, so numbers don’t all fly in an identical straight line.
  • DefaultGravity: A constant downward (or upward) acceleration applied over the animation’s lifetime.
  • ZOrder: Where the Slate canvas sits relative to other viewport widgets.

Override ExtractCombatText, ExtractTextColor, ExtractShadowColor, or ProcessDefaultAnimation in a Blueprint child class to customize text formatting or replace the built-in animation curve entirely.


  1. Start with one root tag (e.g. Damage) mapped to a single renderer, then branch out only when a specific damage type needs different visuals or performance characteristics.
  2. Reserve Niagara for volume. If a damage type can realistically spike into the dozens per second (DoTs, AoE ticks), route it to Niagara so the batched array update keeps cost flat.
  3. Reserve UMG for meaning. Use it for numbers the player should specifically notice and read — accumulating damage, boss health chunks, critical hits — where the pooled widget cost is easily justified.