1. Вики
  2. /Анимации
  3. /Контроллеры анимаций

Контроллеры анимаций

Переключай анимации мобов в Minecraft Bedrock с помощью контроллеров анимаций: состояния, переходы, плавное смешивание, on_entry и on_exit, а также переменные.

Моб редко проигрывает всего одну анимацию. Наш рубиновый голем должен стоять и покачиваться, ходить, когда двигается, и поднимать кулаки, когда замечает врага. Контроллер анимаций решает, какая из них играет прямо сейчас.

Этот гайд продолжает Анимации сущностей. Если ты ещё не делал анимацию, сначала прочитай его.

Файлы

Пакет ресурсов
RP/
  animations/
    ruby_golem.animation.json
  animation_controllers/
    ruby_golem.animation_controllers.json
  entity/
    ruby_golem.entity.json

Представь его как набор комнат

Контроллер - это набор состояний. Представь каждое состояние как комнату:

  • Моб всегда находится ровно в одной комнате.
  • В каждой комнате есть список анимаций, которые играют, пока моб внутри.
  • В каждой комнате есть двери (переходы). На двери висит проверка на Molang. Когда проверка истинна, моб проходит в другую комнату.

Для начала у нашего голема две комнаты: idle и walking.

Шаг 1: покой и ходьба

Файлы контроллеров лежат в папке animation_controllers пакета ресурсов:

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
        }
      }
    }
  }
}

Читается это так:

  1. Голем начинает в idle и проигрывает анимацию idle.
  2. Как только его скорость превышает 0.1, он переходит в walking и вместо этого играет walk.
  3. Когда он замедляется ниже 0.05, он возвращается в idle.
  4. Каждое переключение плавно длится 0.2 секунды, поэтому ноги не дёргаются.

Названия внутри animations - это короткие имена из клиентской сущности, а не длинные имена с animation.. Подробнее об этом в шаге 2.

Два разных числа - это специально

Вход (> 0.1) и выход (< 0.05) используют разные числа. Если бы они были одинаковыми, голем, который движется ровно с этой скоростью, мог бы прыгать между комнатами каждый кадр и выглядеть дёргано.

Поля контроллера

ПолеЧто делает
initial_stateСостояние, в котором моб начинает. Если его не указать, игра ищет состояние с названием default.
statesВсе состояния по названиям.

Названия контроллеров начинаются с controller.animation.. Удобная схема: controller.animation.<моб>.<задача>, например controller.animation.ruby_golem.move.

Внутри состояния

ПолеЧто делает
animationsЧто играет в этом состоянии. Короткие имена или короткие имена со смешиванием.
transitionsДвери из этого состояния, проверяются по порядку.
blend_transitionСколько секунд длится плавный переход из этого состояния в следующее.
blend_via_shortest_pathtrue заставляет кости при переходе поворачиваться коротким путём.
on_entryЧто выполнить один раз, когда моб входит в состояние.
on_exitЧто выполнить один раз, когда моб выходит из состояния.
variablesЗначения, которые вычисляются для этого состояния, смотри ниже.
particle_effectsЧастицы, которые показываются в этом состоянии.
sound_effectsЗвуки, которые играют при входе в это состояние.

Частицы и звуки описаны в гайде События анимаций.

Переходы

transitions - это список. В каждой записи один ключ (состояние, куда идти) и одна проверка на Molang:

Состояние с тремя дверями
"transitions": [
  { "alert": "query.has_target" },
  { "swimming": "query.is_in_water" },
  { "idle": "query.modified_move_speed < 0.05" }
]
  • Проверки идут сверху вниз. Побеждает первая истинная.
  • За один кадр происходит только один переход.
  • Если ни одна не истинна, моб остаётся на месте.

Поэтому самую важную дверь ставь первой. Здесь заметить врага важнее всего остального.

Смешивание внутри состояния

Состояние может проигрывать несколько анимаций сразу. У каждой может быть значение смешивания, как в scripts.animate:

Смешивание по скорости
"walking": {
  "animations": [
    "idle",
    { "walk": "query.modified_move_speed" }
  ]
}

Медленный голем показывает немного ходьбы поверх покачивания. Быстрый - ходьбу целиком.

Шаг 2: подключаем к мобу

Контроллер указывается в карте animations клиентской сущности так же, как анимация. Потом ты запускаешь его из 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"
  ]
}

Заметь, что idle и walk в animate больше нет. Теперь их запускает контроллер. Если их оставить, они будут играть дважды.

Можно запускать несколько контроллеров одновременно. У каждого своё текущее состояние. Частая схема: один контроллер для ног и тела, другой для рук.

Шаг 3: состояние тревоги

Пусть голем поднимает кулаки, пока у него есть цель. Добавь третье состояние и дверь в него из обоих других:

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
  }
}

В alert голем держит кулаки поднятыми и всё равно идёт, когда гонится за тобой.

Ждём окончания анимации

Некоторые анимации должны проиграть один раз и до конца, например рёв. Для этого есть два запроса:

ЗапросИстинен, когда
query.all_animations_finishedВсе анимации в состоянии дошли до конца
query.any_animation_finishedХотя бы одна из них дошла до конца
Рёв, который играет один раз
"roar": {
  "animations": ["roar"],
  "transitions": [
    { "alert": "query.all_animations_finished" }
  ]
}

Это работает только для анимаций, которые не зациклены. Зацикленная анимация никогда не заканчивается.

on_entry и on_exit

on_entry выполняется один раз, когда моб входит в состояние, а on_exit - один раз, когда выходит. В пакете ресурсов они выполняют Molang, и это удобно, чтобы задавать переменные:

Считаем, сколько раз голем злился
"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" }]
}

В пакете поведения эти же списки могут выполнять ещё и команды и события сущности. Смотри События анимаций.

Переменные состояния

Состояние может вычислять собственные значения через variables. Самое полезное здесь - remap_curve: он переводит один диапазон чисел в другой.

Чем быстрее, тем сильнее размах
"walking": {
  "variables": {
    "swing": {
      "input": "query.modified_move_speed",
      "remap_curve": {
        "0.0": 0.3,
        "1.0": 1.0
      }
    }
  },
  "animations": [{ "walk": "variable.swing" }]
}

Когда скорость 0, variable.swing равна 0.3. Когда 1, она равна 1.0. Между ними игра проводит прямую линию. Так что даже медленный голем немного показывает ходьбу.

Если что-то не работает

Что ты видишьСкорее всего, причина
Ничего не играетКонтроллер есть в animations, но не в scripts.animate
Анимация играет в два раза сильнееОна есть и в scripts.animate, и в состоянии контроллера
Моб застревает в состоянииНи один переход из него никогда не становится истинным. Проверь Molang на его дверях
Одноразовая анимация никогда не заканчиваетсяУ неё стоит "loop": true, поэтому all_animations_finished никогда не истинен
Моб мигает между двумя состояниямиПроверки входа и выхода пересекаются. Используй два разных числа
Журнал контента пишет, что состояния нетПереход указывает на название состояния с опечаткой

Больше помощи в гайде Когда что-то сломалось.

Что дальше

Анимации: Гайды

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