Damage Visualization
Damage Visualization plays a directional hit-reaction animation when the character receives enough damage from an external attacker. Use it to show where a bullet, melee strike, or another sourced hit came from while the additive Animator layer preserves the underlying locomotion pose.
The built-in ability selects one of four reactions: front-left, front-right, back-left, or back-right. Damage with no attacker, such as the standard fall-damage workflow, does not start this ability.
Before you begin
- The character needs Ultimate Character Locomotion, a Health component that sends OnHealthDamage, and an Animator configured for UCC parameters.
- The damage source must provide a non-null source owner as the attacker. A visual hit does not play when the Health event’s attacker is null.
- The shipped Animator expects Damage Visualization to use Ability Index Parameter
10and direction values0through3.
Add Damage Visualization
- Select the character GameObject.
- In the Ultimate Character Locomotion component, expand Abilities.
- Select the plus button and add Damage Visualization.
- Keep Enabled selected and both Start Type and Stop Type set to Manual. The Health event starts the ability, and its completion trigger stops it.
- Place Damage Visualization near the top of the ability list. Its default index is
10; a higher-priority active nonconcurrent ability can prevent it from starting, while Damage Visualization can stop lower-priority nonconcurrent abilities. - Keep Ability Index Parameter at
10when using the shipped Animator Controller. - Set Min Damage Amount and configure Damage Visualization Complete Event for either a duration or an animation event.
- Apply external damage from each side in Play Mode and confirm the four Animator branches match the hit positions.
Choose which damage shows a reaction
Min Damage Amount is the inclusive threshold for a reaction. The default is 0: damage starts the ability when its amount is equal to or greater than the threshold.
- Raise the value when small damage-over-time ticks should not interrupt other ability logic.
- Keep it low when every external impact needs visible feedback.
- Damage below the threshold is ignored before direction selection.
The attacker check is separate from the amount. The Health component derives the attacker from the damage source’s source owner. If that value is null, Damage Visualization treats the damage as internal and does not start. This is why standard fall damage has no reaction, but it also means a custom projectile or hazard must identify its source owner when a reaction is expected.
How direction selects an animation
The ability transforms the damage position into the character’s local space at the moment of the hit:
AbilityIntData |
Local hit position | Built-in reaction |
|---|---|---|
0 |
Front and left | Front Left |
1 |
Front and right | Front Right |
2 |
Back and left | Back Left |
3 |
Back and right | Back Right |
The default calculation uses the hit position, not the force direction or attacker position. Supply the actual world-space impact point when dealing damage. A result of -1 prevents the ability from starting; the built-in calculation returns -1 when the local hit position has no front or back component.
The shipped transitions are in Additive Layer -> Damage Visualization. The additive layer lets the hit reaction overlay movement such as running or jumping, even though Damage Visualization itself is a nonconcurrent character ability whose list priority can affect other abilities.
Choose how the reaction completes
Damage Visualization Complete Event is an Animation Event Trigger with two modes:
- Disable Wait For Animation Event to stop after Duration. The default duration is
0.2seconds. Use this for simple, consistent reactions that do not require clip-specific timing. - Enable Wait For Animation Event to keep the ability active until OnAnimatorDamageVisualizationComplete is received. Add an Animation Event to every reaction clip that can play, set its function to
ExecuteEvent, and useOnAnimatorDamageVisualizationCompleteas its string value.
Choose the duration or event point at the moment the ability should release its priority. The visual animation can blend out through the Animator after that point.
How Damage Visualization runs
Damage Visualization listens for OnHealthDamage. It first checks Min Damage Amount and the attacker, then calls GetDamageTypeIndex with the damage amount, world position, force, and attacker.
When the returned index is not -1, the ability starts manually. Ability Index becomes 10 by default, and AbilityIntData exposes the selected direction index to the Animator. The ability either schedules its completion by Duration or waits for the Animator event.
Completion stops the ability and cancels any pending scheduled event. Destroying the character unregisters both damage and Animator-completion listeners.
Verify in Play Mode
- Keep the Ultimate Character Locomotion and Animator Inspectors visible.
- Apply damage equal to Min Damage Amount with a valid attacker and confirm Damage Visualization becomes active.
- Confirm Ability Index is
10and AbilityIntData is0,1,2, or3for front-left, front-right, back-left, and back-right hits. - Confirm the corresponding additive reaction plays without replacing the underlying locomotion animation.
- Apply damage below Min Damage Amount and confirm the ability does not start.
- Apply damage with a null attacker, including fall damage, and confirm the ability does not start.
- In duration mode, confirm the ability stops after the configured Duration.
- In event mode, confirm every reaction clip sends OnAnimatorDamageVisualizationComplete and the ability stops at the intended frame.
- Start a lower-priority nonconcurrent ability, apply damage, and confirm Damage Visualization takes priority. Repeat with a higher-priority ability and confirm the intended priority rule.
Troubleshoot Damage Visualization
- The character takes damage but the ability never starts: confirm the amount meets Min Damage Amount, the Health event has a non-null attacker, and Damage Visualization is enabled.
- A projectile or hazard causes no reaction: check its DamageSource and source owner. Health sends a null attacker when no source owner is available.
- Fall damage does not play a hit reaction: this is expected because fall damage has no external attacker.
- The wrong directional animation plays: pass the world-space impact position rather than the attacker position or force vector, then verify the character’s facing at the damage frame.
- Every hit plays the same clip: confirm the Animator transitions test AbilityIntData values
0through3and the damage position changes between tests. - No reaction plays while another ability is active: place Damage Visualization above the ability it should interrupt. A higher-priority nonconcurrent ability can block it.
- Movement or another action stops unexpectedly: Damage Visualization is nonconcurrent and can stop lower-priority nonconcurrent abilities. Adjust list priority only after deciding which response should win.
- The ability stops before the visible reaction finishes: increase Duration or move OnAnimatorDamageVisualizationComplete later in the clip.
- The ability remains active indefinitely: when Wait For Animation Event is enabled, confirm every reachable reaction clip sends OnAnimatorDamageVisualizationComplete with the exact string value.
- A custom reaction never plays: confirm the override returns the expected new AbilityIntData value and the Additive Layer contains a transition for that value.
Related topics
- Health explains damage sources and the OnHealthDamage event.
- Animator Controller explains the additive layer used for the reaction states.
- Animator Parameters explains Ability Index and AbilityIntData.
- Default Animator Values lists Damage Visualization’s default index of
10. - Animation Event Trigger explains duration and Animator-event completion modes.
- Abilities explains priority, manual activation, and nonconcurrent ability behavior.
Developer reference
Override GetDamageTypeIndex to add another damage category. Return -1 to suppress the reaction. This example uses AbilityIntData 4 for damage above 20 and preserves the built-in directional result for other hits.
using UnityEngine;
using Opsive.UltimateCharacterController.Character.Abilities;
[System.Serializable]
public class MyDamageVisualizationAbility : DamageVisualization
{
/// <summary>
/// Returns the value assigned to the AbilityIntData Animator parameter.
/// </summary>
protected override int GetDamageTypeIndex(float amount, Vector3 position, Vector3 force, GameObject attacker)
{
if (amount > 20) {
return 4;
}
return base.GetDamageTypeIndex(amount, position, force, attacker);
}
}
Replace the built-in ability with the subclass so both do not respond to the same Health event. In the Animator Controller, add the custom clip to Additive Layer -> Damage Visualization and create a transition whose AbilityIntData condition equals 4.

If the ability waits for an animation event, add OnAnimatorDamageVisualizationComplete to the custom clip as well.
The feature-specific runtime surface is intentionally small:
- AbilityIntData: returns the selected damage type index.
- GetDamageTypeIndex(float, Vector3, Vector3, GameObject): is the protected virtual extension point for reaction selection.
- OnHealthDamage: supplies the amount, position, force, attacker, and hit Collider used to trigger the workflow.
- OnAnimatorDamageVisualizationComplete: stops the active reaction.
Min Damage Amount and Damage Visualization Complete Event are serialized Inspector settings but are not exposed as public properties by the current Damage Visualization class.