How-To: Author Motion Presets
Motion presets live in a UCrimsonCombatTextMotionSet asset as ordinary editable rows keyed by gameplay tag. Adding your own needs no C++.
1. Create the asset
Content Browser right-click > Crimson > Combat Text > Motion Set. A new asset arrives pre-seeded with ten editable built-in presets, so you are never staring at an empty map:
| Preset tag | Feel |
|---|---|
CrimsonCombatText.Motion.FloatUp | Gentle straight rise with a soft ease-out. The everyday damage number. |
CrimsonCombatText.Motion.ArcOut | Rises then falls away in an arc. Classic ballistic combat text. |
CrimsonCombatText.Motion.Burst | Wide fast scatter, short life. Multi-hit and AoE. |
CrimsonCombatText.Motion.CritPunch | Hard scale punch, minimal drift, long hang time. |
CrimsonCombatText.Motion.Static | No movement. Fades in place. Good for status words. |
CrimsonCombatText.Motion.Drift | Slow, small, long-lived rise with a wide gentle fan. Ticks of a damage-over-time. |
CrimsonCombatText.Motion.Sink | Falls away instead of rising. Blocked and absorbed damage - anything that failed to land. |
CrimsonCombatText.Motion.Hover | Quick hop, then a long hang in place. Status words: Miss, Immune, Dodge. |
CrimsonCombatText.Motion.Shiver | Rapid side-to-side wobble on the way up. Ice, lightning, anything that should read as unstable. |
CrimsonCombatText.Motion.Pulse | Rises while the number beats twice. Heals and buffs that should feel alive. |
Point the registry's MotionSet at this asset, then reference presets from a style's MotionPreset tag.
CrimsonCombatText.Motion. A Merge checkbox in the preview's chrome row plays the merged form instead - held at MergeHoldAlpha, punching on a repeating cycle - so the merge fields are tuned against what they actually look like. See How-To: Author Styles in the Registry Editor.2. Add your own
Add a gameplay tag under CrimsonCombatText.Motion and a matching row. Tune the amplitudes first, then shape the curves:
| Field | What to reach for it for |
|---|---|
Duration | How long it lives |
RiseDistance | How far it travels up over the full lifetime |
SpreadDistance | Lateral amplitude at full fan deflection |
RiseCurve | The shape of the rise. Empty = linear |
SpreadCurve | The shape of the lateral travel. Empty = linear |
ScaleCurve | Punch and settle. Empty = constant 1 |
OpacityCurve | Fade. Empty = opaque until 80%, then linear to 0 |
RiseStaggerPerSlot | Extra rise per concurrent hit, as a fraction of RiseDistance. Ladders the end heights of a burst |
RiseJitter | Random rise variation as a fraction of RiseDistance, rolled once per pop |
DurationJitter | Random variation in Duration as a fraction of it, rolled once per pop, so pops in a burst climb at different speeds |
MergeHoldAlpha | Where the motion parks when a hit merges into this pop, as a lifetime alpha |
MergePunchDuration | How long the merge punch runs, in seconds. 0 = hold with no punch |
MergePunchScaleCurve | The punch's shape, as a scale multiplier on the held sample. Empty = a sine hump 1 -> 1.3 -> 1 |
MergePunchRiseCurve | Extra upward layout units over the punch, added to the held sample. Empty = 0 |
Duration restretches the whole motion without redrawing anything.3. Stop hits stacking
bUseSpreadFan deflects concurrent hits on the same target to alternating sides. Slot 0 goes straight up, then -1/N, +1/N, -2/N and so on out to FanWidth. It is deterministic, so the same burst always reads the same way; RandomJitter adds controlled wobble on top if perfect regularity looks mechanical.
The fan only moves hits sideways, and it saturates at FanSlots - so past that slot a burst on one target still ends at a single height and the numbers pile up. RiseStaggerPerSlot ladders the END heights as well: slot 1 travels RiseDistance * (1 + RiseStaggerPerSlot), slot 2 twice that step, and so on up to FanSlots. Negative values ladder downward; 0 restores a flat stack. RiseJitter then adds a per-pop roll on top, so a second volley does not replay the identical ladder. DurationJitter varies each pop's lifetime the same way, because different end heights still read as one clump when every number climbs in lockstep - built-in defaults are FloatUp 0.15, ArcOut 0.20, Burst 0.25, CritPunch 0.10, Static 0, Drift 0.30, Sink 0.15, Hover 0.10, Shiver 0.20, Pulse 0.15.
| Preset | RiseStaggerPerSlot | RiseJitter |
|---|---|---|
FloatUp | 0.10 | 0.06 |
ArcOut | 0.08 | 0.10 |
Burst | 0.15 | 0.12 |
CritPunch | 0.00 | 0.05 |
Static | 0.00 | 0.00 |
Drift | 0.12 | 0.10 |
Sink | 0.08 | 0.06 |
Hover | 0.15 | 0.05 |
Shiver | 0.10 | 0.08 |
Pulse | 0.10 | 0.06 |
RiseDistance, not offsets - so a motion that deliberately does not travel (Static, RiseDistance 0) stays pinned to its anchor however many hits land at once. The multiplier is also clamped at 0, so a large negative stagger cannot flip a pop downward.CrimsonCombatText.Motion.Static and every pop stays on the anchor.SpreadDecayTime in project settings controls how long a burst keeps fanning outward before the next flurry restarts from center.
4. Shape what a merge looks like
When a style merges repeat hits into one climbing number - AggregationWindow or ScopeTag - the pop does not restart and does not rewind to the anchor. It holds at MergeHoldAlpha and fires a punch on top, and the four fields under the Motion | Merge category are where you shape that.
| Field | Reach for it to |
|---|---|
MergeHoldAlpha | Move where the number parks. Lower parks it closer to the anchor and leaves more travel for the fade; higher parks it further up. Default 0.6 |
MergePunchDuration | Set how long each reaction lasts. Shorter reads as a snappier tick; 0 turns the punch off and leaves a plain hold. Default 0.25s |
MergePunchScaleCurve | Shape the size kick. Empty gives a sine hump from 1 to 1.3 and back, which is a sensible default for most numbers |
MergePunchRiseCurve | Add a small hop. The values are layout units added to the held offset, so a peak of 8 nudges the number up and back down over the punch |
The punch has its own alpha, separate from the lifetime alpha, so back-to-back merges re-punch while the base motion stays parked. The built-in presets are tuned for their own feel: FloatUp holds at 0.55 and punches for 0.22s peaking at 1.30 scale with an 8-unit hop, Drift 0.50 / 0.18s peaking at 1.18 with a 4-unit hop, CritPunch 0.50 / 0.30s peaking at 1.45 with a 14-unit hop, and Hover and Static hold at 0.60 and punch for 0.25s with scale only and no hop, so a pinned status word reacts without moving.
MergeHoldAlpha and stops there, then punches on a cycle - it never snaps back to the anchor and never restarts. Set MergePunchDuration to 0 and the punching stops while the hold stays.Overriding motion from a modifier
A modifier's MotionPresetOverride swaps the motion wholesale. Pointing a Crit modifier at CrimsonCombatText.Motion.CritPunch gives every critical hit the punch motion, whatever base style it resolved to - no per-damage-type rows needed.