CrimsonCombatTextComing to FabFree
Get early access on Discord

Floating combat text done right — tag-styled, curve-animated, pooled, and replicated for multiplayer.

Free · Gameplay · Unreal Engine 5

Damage numbers that pop, without the frame drops.

Floating combat text for damage, healing, and custom values. The server broadcasts one event; every client resolves a style from a hierarchical tag registry, plays a curve-authored motion preset, and recycles a pooled widget — so combat reads clearly on every machine and never hitches under a flurry of hits.

Video coming soon

Why CrimsonCombatText

Everything you need to show numbers above actors — pooled for performance, styled by tags, and correct in multiplayer.

Hierarchical tag-to-style registry

A UCrimsonCombatTextRegistry maps gameplay tags to styles hierarchically — a hit tagged Damage.Fire.Burn falls back to Damage.Fire, then Damage, then DefaultStyle. You author only the specificity you care about, and one Damage row already covers every damage type.

Modifiers instead of combinations

Conditions that cut across types — Crit, Blocked, Absorbed — are Modifiers that layer onto whichever style matched, in ApplyOrder. A registry grows as styles plus conditions instead of styles times conditions, so Damage.Fire.Crit never needs its own row.

Pooled views, capped and recycled

The subsystem simulates every live instance in one loop and hands the frame to a renderer. Views are pooled and recycled — never destroyed mid-session — MaxActiveTexts caps concurrent pops and retires the oldest first, and creation is throttled per frame when the pool runs dry.

Multiplayer by design

A UCrimsonCombatTextReplicationComponent on your GameState sends each event over unreliable RPCs — one multicast, or per-client delivery when ServerCullDistance is set. WorldLocation is resolved and net-quantized server-side, so clients render without re-deriving anything.

Curve-authored motion presets

Motion lives in a shared UCrimsonCombatTextMotionSet — five built-in presets (FloatUp, ArcOut, Burst, CritPunch, Static) plus your own. Curves run over a normalized 0–1 lifetime, so motion always completes exactly at Duration and repeats identically instead of scattering.

Per-player display filters

An optional UCrimsonCombatTextPlayerSettings component lets each player choose what they see: own, ally, enemy, and incoming damage, heals, a crits-only mode, a max-distance cap, widget scale, and a number-format override — with a hook that bridges to your team system.

A closer look

One server event, every client renders locally

On the server, build a FCrimsonCombatTextEvent and call BroadcastCombatText — from an AttributeSet's PostGameplayEffectExecute, an ability, or Blueprint. It validates authority, resolves the spawn location from the target's UCrimsonCombatTextTargetComponent, and sends. Each client's subsystem filters, styles, and displays from there.

Styled by tags, moved by curves

Tags resolve a style up the hierarchy, modifiers layer conditions on top, and the style points at a motion preset. Add a new look by adding a row — no branching code, no per-combination explosion, and editing one preset restyles every effect that references it.

Bursts that read instead of blur

A deterministic spread fan deflects concurrent hits to alternating sides, AggregationWindow folds repeat hits on the same target into one climbing number, and scopes accumulate everything landed during a stagger or posture break into a single summary pop when the state ends.

Every player sees their own fight

Drop a UCrimsonCombatTextPlayerSettings component on the local PlayerController and each player tunes their own clutter: hide enemy damage, show only crits, cap by distance — while incoming damage to you always shows. Bind the team hook to your faction system and ally-vs-enemy filtering just works.

Technical details

Engine
UE 5.8
Platforms
Windows, Mac, Linux
Blueprint-ready
Yes
C++ required
No
Network replicated
Yes
Dependencies
CrimsonCommon, UMG, GameplayTags, GameplayAbilities, DeveloperSettings
Last updated
July 2026

Frequently asked questions

Do I need C++ to use it?
No. The registry, motion set, widget Blueprint, project settings, target component, and per-player filters are all Blueprint-accessible, and BroadcastCombatText is BlueprintCallable. The C++ snippets in the docs show the common GAS integration point, but they're optional — C++ is there if you want it.
Does it depend on other Crimson plugins?
Only CrimsonCommon, the free shared layer every Crimson plugin builds on (logging and shared utilities). Beyond that it runs on stock engine modules — UMG, GameplayTags, GameplayAbilities, DeveloperSettings — and needs nothing else from the suite.
Does it work in multiplayer?
Yes — that's the design. A replication component on your GameState sends each event to clients over unreliable RPCs, with the spawn location resolved server-side; each client then applies its own filters and renders locally. Set ServerCullDistance and delivery switches to per-client, so distant players never pay for pops they can't see. For purely local use, call RequestCombatText on the subsystem directly.
Will hundreds of numbers tank my framerate?
No. Views are pooled and recycled, MaxActiveTexts caps concurrent pops and retires the oldest first, and creation is throttled per frame when the pool is exhausted. For ARPG or bullet-hell densities there's an optional batched Niagara renderer that draws every number from one system — trading rich text for scale. The subsystem also never runs on dedicated servers or in editor preview worlds.
Is it free?
Yes. CrimsonCombatText is free on Fab — drop it in and start showing numbers.

Make every hit land — on screen

CrimsonCombatText is free and quick to wire up: enable the plugin, author a motion set and style registry, add the component to your GameState, and broadcast from the server. It even ships with demo content pre-wired, so numbers pop before you author anything. The Quick Start walks through it end to end.