1. Wiki
  2. /Animations
  3. /Animation controllers

Animation controllers

Switch mob animations in Minecraft Bedrock with animation controllers: states, transitions, smooth blending, on_entry and on_exit, and variables.

A mob rarely plays just one animation. Our Ruby golem should stand and sway, walk when it moves, and raise its fists when it spots an enemy. An animation controller decides which of those plays right now.

This guide builds on Entity animations. Read that first if you have not made an animation yet.

The files

Resource pack
RP/
  animations/
    ruby_golem.animation.json
  animation_controllers/
    ruby_golem.animation_controllers.json
  entity/
    ruby_golem.entity.json

Think of it as a set of rooms

A controller is a set of states. Think of each state as a room:

  • The mob is always in exactly one room.
  • Each room has a list of animations that play while the mob is inside.
  • Each room has doors (transitions). A door has a Molang check on it. When the check is true, the mob walks through to the other room.

Our golem has two rooms to start with: idle and walking.

Step 1: idle and walk

Controller files go in the animation_controllers folder of the resource pack:

RP/animation_controllers/ruby_golem.animation_controllers.json
{
  "format_version": "1.10.0",
  "animation_controllers": {
    "controller.animation.ruby_golem.move": {
      "initial_state": "idle",
      "states": {
        "idle": {
          "animations": ["idle"],
          "transitions": [
            { "walking": "query.modified_move_speed > 0.1" }
          ],
          "blend_transition": 0.2
        },
        "walking": {
          "animations": ["walk"],
          "transitions": [
            { "idle": "query.modified_move_speed < 0.05" }
          ],
          "blend_transition": 0.2
        }
      }
    }
  }
}

Read it like this:

  1. The golem starts in idle and plays the idle animation.
  2. As soon as its speed goes over 0.1, it moves to walking and plays walk instead.
  3. When it slows below 0.05, it goes back to idle.
  4. Each switch fades over 0.2 seconds, so the legs do not snap.

The names inside animations are the nicknames from the client entity, not the long animation. names. More on that in Step 2.

Two different numbers on purpose

The way in (> 0.1) and the way out (< 0.05) use different numbers. If they were the same, a golem moving at exactly that speed could flip between rooms every frame and look jittery.

Controller fields

FieldWhat it does
initial_stateThe state the mob starts in. Leave it out and the game looks for a state called default.
statesAll the states, by name.

Controller names start with controller.animation.. A good pattern is controller.animation.<mob>.<job>, like controller.animation.ruby_golem.move.

Inside a state

FieldWhat it does
animationsWhat plays in this state. Nicknames, or nicknames with a blend.
transitionsThe doors out of this state, checked in order.
blend_transitionSeconds to fade from this state into the next one.
blend_via_shortest_pathtrue makes the fade turn bones the short way round.
on_entryThings to run once when the mob enters the state.
on_exitThings to run once when the mob leaves the state.
variablesValues worked out for this state, see below.
particle_effectsParticles to show while in this state.
sound_effectsSounds to play when entering this state.

Particles and sounds are explained in Animation events.

Transitions

transitions is a list. Each entry has one key (the state to go to) and one Molang check:

A state with three doors
"transitions": [
  { "alert": "query.has_target" },
  { "swimming": "query.is_in_water" },
  { "idle": "query.modified_move_speed < 0.05" }
]
  • The checks run from top to bottom. The first one that is true wins.
  • Only one transition happens per frame.
  • If none are true, the mob stays where it is.

So put the most important door first. Here, spotting an enemy beats everything else.

Blending inside a state

A state can play several animations at once. Each one can have a blend value, just like in scripts.animate:

Blend by speed
"walking": {
  "animations": [
    "idle",
    { "walk": "query.modified_move_speed" }
  ]
}

A slow golem shows a little walk on top of its sway. A fast one shows the full walk.

Step 2: connect it to the mob

A controller is listed in the client entity's animations map, the same way as an animation. Then you play it from scripts.animate:

RP/entity/ruby_golem.entity.json
"animations": {
  "idle": "animation.ruby_golem.idle",
  "walk": "animation.ruby_golem.walk",
  "fists_up": "animation.ruby_golem.fists_up",
  "look_at_target": "animation.common.look_at_target",
  "move_controller": "controller.animation.ruby_golem.move"
},
"scripts": {
  "animate": [
    "look_at_target",
    "move_controller"
  ]
}

Notice that idle and walk are not in animate any more. The controller plays them now. If you leave them in, they play twice.

You can run several controllers side by side. Each one keeps its own current state. A common setup is one controller for the legs and body, and another for the arms.

Step 3: an alert state

Let's make the golem raise its fists while it has a target. Add a third state and a door to it from both other states:

RP/animation_controllers/ruby_golem.animation_controllers.json
"states": {
  "idle": {
    "animations": ["idle"],
    "transitions": [
      { "alert": "query.has_target" },
      { "walking": "query.modified_move_speed > 0.1" }
    ],
    "blend_transition": 0.2
  },
  "walking": {
    "animations": ["walk"],
    "transitions": [
      { "alert": "query.has_target" },
      { "idle": "query.modified_move_speed < 0.05" }
    ],
    "blend_transition": 0.2
  },
  "alert": {
    "animations": [
      "fists_up",
      { "walk": "query.modified_move_speed" }
    ],
    "transitions": [
      { "idle": "!query.has_target" }
    ],
    "blend_transition": 0.3
  }
}

In alert the golem keeps its fists up and still walks when it chases you.

Waiting for an animation to finish

Some animations should play once, all the way through, like a roar. Two queries help with that:

QueryTrue when
query.all_animations_finishedEvery animation in the state has reached its end
query.any_animation_finishedAt least one of them has reached its end
A roar that plays once
"roar": {
  "animations": ["roar"],
  "transitions": [
    { "alert": "query.all_animations_finished" }
  ]
}

These only work for animations that do not loop. A looping animation never finishes.

on_entry and on_exit

on_entry runs once when the mob walks into a state, on_exit runs once when it leaves. In a resource pack they run Molang, which is handy for setting variables:

Count how often the golem got angry
"alert": {
  "on_entry": ["variable.times_alerted = (variable.times_alerted ?? 0) + 1;"],
  "on_exit": ["variable.calm_since = query.life_time;"],
  "animations": ["fists_up"],
  "transitions": [{ "idle": "!query.has_target" }]
}

In a behavior pack the same lists can also run commands and entity events. See Animation events.

State variables

A state can work out its own values with variables. The handy part is remap_curve: it turns one range of numbers into another.

Swing harder the faster it goes
"walking": {
  "variables": {
    "swing": {
      "input": "query.modified_move_speed",
      "remap_curve": {
        "0.0": 0.3,
        "1.0": 1.0
      }
    }
  },
  "animations": [{ "walk": "variable.swing" }]
}

When the speed is 0, variable.swing is 0.3. When it is 1, it is 1.0. In between, the game draws a straight line. So even a slow golem shows a bit of walk.

When something goes wrong

What you seeMost likely cause
Nothing playsThe controller is in animations but not in scripts.animate
An animation plays twice as strongIt is both in scripts.animate and in a controller state
The mob gets stuck in a stateNo transition out of it is ever true. Check the Molang on its doors
A once-only animation never endsIt has "loop": true, so all_animations_finished is never true
The mob flickers between two statesThe checks in and out overlap. Use two different numbers
Content Log says a state is missingA transition points to a state name with a typo

More help is in Troubleshooting.

What next

Animations: Guides

We use cookies to improve your experience and analyse site traffic. Learn more