How Bedrock Tracks Damage frames
When an entity takes damage from an attack, fall, or environmental hazard, the engine starts an internal countdown timer on that entity. This timer controls both the brief invulnerability window (often called hurt resistance) and the red color tint applied by the base entity shader. Because this timer is synced to the client automatically, Resource Pack animations and animation controllers can read it directly using Molang without needing any custom Behavior Pack events or scripts.
Three Molang queries expose this damage state to your animations. Choosing the right one depends on whether you are triggering a state transition in an animation controller or driving a mathematical curve directly inside an animation bone.
| Molang Query | What it returns | Common use |
|---|---|---|
| query.hurt_time | Integer counting down from the max hurt duration to 0 in ticks (usually starts at 10). | Triggering an animation controller state the moment it is greater than 0. |
| query.max_hurt_time | The starting value of the hurt timer (typically 10). | Dividing hurt_time to get a normalized 0.0 to 1.0 progress value. |
| query.hurt_direction | A directional scalar (-1 or 1) used by vanilla mobs to tilt away from damage. | Multiplying Z or X rotation so the flinch leans away from the hit. |
Creating the Hurt Animation
A good hurt animation is short, sharp, and blends cleanly on top of whatever the entity is already doing. Since the standard hurt timer lasts 10 ticks, a hurt animation is usually 0.5 seconds long. If you make it longer than half a second, rapid attacks from a player will cut the animation off before it finishes, unless you specifically design your controller to re-trigger cleanly.
Unless you want the mob to freeze its legs when hit, you should only keyframe the upper body, head, or arms in your hurt animation. Because Bedrock animations blend additively or by bone override depending on how they are layered, leaving the leg bones out of the hurt animation allows the entity to keep walking or running while its torso flinches.
{
"format_version": "1.8.0",
"animations": {
"animation.stone_golem.hurt": {
"loop": false,
"animation_length": 0.5,
"bones": {
"body": {
"rotation": {
"0.0": [0.0, 0.0, 0.0],
"0.1": [-15.0, 0.0, "query.hurt_direction * 8.0"],
"0.5": [0.0, 0.0, 0.0]
}
},
"head": {
"rotation": {
"0.0": [0.0, 0.0, 0.0],
"0.15": [-25.0, 0.0, 0.0],
"0.5": [0.0, 0.0, 0.0]
}
}
}
}
}
}Setting Up the Animation Controller
You should run your hurt logic in its own dedicated animation controller, separate from your walk and attack controllers. If you put the hurt state inside your main movement controller, taking damage will interrupt the walk or attack state, causing the mob's legs to snap back to their default pose for half a second every time it is hit.
In the controller below, the default state waits for `query.hurt_time > 0`. As soon as the entity takes damage, the controller transitions to the `hurt` state, plays the flinch animation, and waits for `query.any_animation_finished` to return to `default`. Adding `blend_transition` gives the return transition a smooth 0.1-second fade out so the bones do not pop if the timer ends early.
{
"format_version": "1.10.0",
"animation_controllers": {
"controller.animation.stone_golem.damage": {
"initial_state": "default",
"states": {
"default": {
"transitions": [
{
"hurt": "query.hurt_time > 0"
}
]
},
"hurt": {
"animations": [
"hurt"
],
"blend_transition": 0.1,
"transitions": [
{
"default": "query.any_animation_finished && query.hurt_time == 0"
}
]
}
}
}
}
}Wiring into the Client Entity
Once the animation and controller files exist, link them both inside the entity's client definition file in the Resource Pack. Map the short name `hurt` to `animation.stone_golem.hurt`, and map a short name for the damage controller.
In the `scripts.animate` array, list the damage controller after your locomotion controller. Bedrock evaluates animations in the order they are listed; placing the damage controller at the bottom ensures that the hurt keyframes override the idle or walking torso rotations during the flinch.
{
"format_version": "1.10.0",
"minecraft:client_entity": {
"description": {
"identifier": "wiki:stone_golem",
"materials": {
"default": "entity_alphatest"
},
"textures": {
"default": "textures/entity/stone_golem"
},
"geometry": {
"default": "geometry.stone_golem"
},
"animations": {
"walk": "animation.stone_golem.walk",
"hurt": "animation.stone_golem.hurt",
"damage_controller": "controller.animation.stone_golem.damage"
},
"scripts": {
"animate": [
{
"walk": "query.modified_move_speed"
},
"damage_controller"
]
},
"render_controllers": [
"controller.render.default"
]
}
}
}Controlling the Red Overlay Flash
When an entity is hurt, the default render controller applies a semi-transparent red overlay across the whole model. This is controlled by the `overlay_color` block inside the render controller definition. If your custom hurt animation already communicates damage clearly—or if you are building a non-living entity like a vehicle, crate, or dummy where a red flash looks out of place—you can remove or change this tint.
To disable or alter the flash, create a custom render controller instead of using `controller.render.default`. If you leave out the `overlay_color` block entirely, the entity will use its standard material default (which still flashes red on most vanilla entity materials). To force the flash off without writing custom shaders, explicitly set the alpha channel of `overlay_color` to `0.0`.
{
"format_version": "1.8.0",
"render_controllers": {
"controller.render.stone_golem": {
"geometry": "Geometry.default",
"materials": [
{
"*": "Material.default"
}
],
"textures": [
"Texture.default"
],
"overlay_color": {
"r": 1.0,
"g": 1.0,
"b": 1.0,
"a": "query.hurt_time > 0 ? 0.4 : 0.0"
}
}
}
}Which versions this applies to
Applies to Minecraft Bedrock 1.10.0 and above. All queries and animation controllers shown are stable and do not require any experimental toggles.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| The entity gets stuck in the final frame of the hurt pose and never animates again. | The hurt animation has "loop": true (or "hold_on_last_frame") and the animation controller is waiting for query.any_animation_finished, which never fires on a looping animation. | Set "loop": false in your hurt animation JSON, or change the controller return transition to solely check "query.hurt_time == 0". |
| Content Log shows: [Animation][error]-controller.animation.stone_golem.damage | animation 'hurt' not found. | The animation controller refers to the short name "hurt", but that short name was either misspelled or never defined inside the "animations" block of the client_entity JSON. | Open the RP/entity/ file and ensure "hurt": "animation.stone_golem.hurt" is listed in description.animations. |
| The hurt animation plays twice in a row from a single sword hit. | The hurt animation is very short (for example, 0.15 seconds), so query.any_animation_finished triggers while query.hurt_time is still counting down from 10, causing the controller to immediately re-enter the hurt state. | Add "&& query.hurt_time == 0" to the transition back to default, or lengthen the animation to 0.5 seconds so it matches the 10-tick hurt window. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
