Как использовать прерывания в Unity Animator на полную

Вау-эффекта в играх можно достигнуть не только неожиданными механиками или плоттвистом, но и анимацией — в мобильных проектах на последнем часто делается особый акцент. Поэтому решил поделиться интересным переводом материала по Unity Animator. Внутри — про приоритетность переходов анимации и грамотное переключение между состояниями.
Механизм прерывания (interruption) в Unity Animator почти не удостоился туториалов и документации, поэтому многие просто перестают его изучать. Только с опытом ко мне пришло понимание, какие есть паттерны и признаки того, что нужно использовать прерывание.
Статью разделил на три части:

- В первой расскажу, что такое прерывания, какие существуют виды и как их лучше использовать.
- Во второй — о признаках, которые указывают на необходимость прерывания. Заглянем в Animator и посмотрим, как можно заменить ненужные переходы.
- В третьей поговорим, как организовать работу в Animator, предотвратить его бесконтрольный рост. Особенно это касается больших команд, в которых несколько людей занимаются одним и тем же аниматором.
Часть 1: что такое «прерывание»?
Прерывание — возможность Unity Animator, которая позволяет остановить переход анимации из одного состояния в другое, чтобы перейти к третьему.
Это единственный способ, который позволяет выполнить бленд от незавершенного перехода к нужному состоянию. С ним вы не полагаетесь на резкую смену состояний или, еще хуже, на переходы Any State. Чуть позже объясню подробнее.
Существует несколько основных типов прерывания:

Current State (Текущее состояние)
Если из определенного состояния предусмотрено несколько переходов и в процессе одного из них будет запущен другой, переключение будет выполнено из текущей точки, как показано на схеме:

Next State (Следующее состояние)
Next State работает аналогично Current State. Но здесь Animator проанализирует переходы от следующего состояния, пока в силе переход от текущего.

Current State Then Next State (Сначала текущее состояние, затем следующее)
Где-то тут людям надоедает теория, и они теряют интерес к теме. Подождите! Это выведет ваш скилл работы с Animator на новый уровень.
Усвоив Current State и Next State, вы точно поймете и третий тип, ведь он — их комбинация. В нем Animator будет покадрово анализировать текущий переход в поисках других, которые можно выполнить из первичного состояния. Если они не будут найдены, Animator проанализирует следующее состояние в поисках подходящего перехода. При этом, переключаясь на новый переход в процессе выполнения предыдущего, Animator будет вести себя точно также, как в примерах выше.
Next State Then Current State (Сначала следующее состояние, затем текущее)
Все как в третьем типе, только порядок анализа будет обратный.
Ordered Interruption (Прерывание в порядке приоритетности)

Для каждого состояния установлена приоритетность переходов (сверху вниз), вот так:

Если раньше вы не знали, зачем перетаскивать компоненты в этом списке — вуаля! Здесь вы ранжируете приоритет переходов.
Когда у Ordered Interruption стоит галочка, Animator выполнит прерывание, только если приоритет нового перехода выше, чем приоритет перехода, выполняемого в данный момент. А чем выше переход расположен в данном списке, тем больше его приоритет.
Часть 2: как определить, где прерываться
В работе с прерываниями сложнее всего определить, когда именно их использовать. А в некоторых ситуациях они необходимы — со временем начинаешь это замечать.
Рассмотрим самый яркий пример. Знакомая схема?

Все сводится к Any State. Верно?
Это первый признак того, что большинство ваших переходов лучше выполнять с помощью прерываний. Переходы от Any State имеют право на жизнь в особых случаях, но большинство людей используют их, когда на самом деле им нужны (ну, вы догадались) прерывания.
Паттерны прерывания Current State:


Часто Any State создают только для перехода ко второму состоянию, когда первое уже началось. Забудьте про это. Используйте прерывания.
Другой пример: у нас есть переход от FirstState к SecondState, но не установлен Exit Time, время перехода равно 0 и задано условие. Прерывание идеально решит эту задачу. Обратиться к Any State нельзя, так как оно уже использовалось слишком часто, и, добавив его к SecondState, вы активируете состояния, которые в данном случае не нужны.
Паттерны прерывания Next State:

Довольно часто встречаются переходы с совершенно безумными Exit Time и условиями перехода. Правильно установите прерывание, и вы проще достигнете той же цели. Как видите, Any State часто встречается там, где нужны прерывания.
Не забудьте, что можно добавлять несколько переходов из двух одинаковых состояний, чтобы успешно использовать прерывание.
Обычно все остальные паттерны — это комбинации из описанных выше примеров.
Типичные ситуации для прерывания:
В некоторых ситуациях прерывания — лучший выход. Немного практики в Animator, и вы легко научитесь их замечать.
a) Следующее действие должно незамедлительно инициировать анимацию.
Такое часто бывает в экшен-играх, где есть множество инпутов и нужно быстро принимать следующие действия.
Например, люди часто используют переходы Any State (или несколько переходов с различными конфигурациями), чтобы плавно перейти от двойного прыжка к рывку.
Необходимо составить карту всех возможных действий, установить продолжительность событий и добавить ее в состояния и переходы. А затем установить прерывания, чтобы корректно переходить от одного события к другому.
b) Анимация запущена, но ситуация изменилась, и нужно перейти к другой последовательности анимаций.
Такое часто происходит с UI Animators, в которых можно пропускать некоторые пункты меню, а подменю могут отображаться поверх всего остального.
Люди часто добавляют несколько Animators на один и тот же объект, и задают условия их включения/выключения, чтобы пропустить одну анимацию и запустить другую. Это еще один пример, где стоит использовать прерывания.
c) Нужно выйти из текущей цепочки анимаций.
Прерывания можно связать друг с другом — получится последовательность прерываний, которая выведет вас к новой цепочке. При этом все состояния будут корректно и своевременно завершены. Здесь можно использовать прерывания Next State.
Часть 3: в Animator все должно быть четко и ясно
Работа с Animator — особый вид искусства. Чем больше практики, тем очевиднее прогресс. Ясный и последовательный воркфлоу всегда положительно влияет на результат.
Рекомендации, чтобы избежать путаницы в Animator:
- Используйте Sub-State Machines и старайтесь обходить переходы к внутренним состояниям. Правильная Sub-State Machine самостоятельно работает на вход и выход, использует переходы, направляющие поток внутрь, и знает, что делать с результатом. Так вы избежите критических проблем при работе в Animator.
- Как можно реже используйте Any State. Подумайте, действительно ли это необходимо. Обратитесь к коллегам. И только если все будут согласны, используйте переходы Any State.
- Если вам кажется, что ваш Animator должен выглядеть проще, чем сейчас — приведите его в порядок. Это лучший способ отточить свои скиллы.
- Блог компании Playgendary
- Разработка игр
- Unity
- Компьютерная анимация
Unity C#. Как можно сделать две разные анимации при одинаковых условиях?
В общем есть скрипт, в котором описаны условия действия двух анимаций:
if (isGrounded && !isDead) State = CharState.knightidle; if (!isDead && Input.GetButtonDown("Fire1")) Attack();
CharState — переменная состояния персонажа
private void Attack() < State = CharState.knightattack; if (Vector3.Distance(transform.position, monster.transform.position) < length) < monster.GetDamage(); >>
Когда скрипт пытается проиграть анимацию knightattack она тут же заменяется обратно на knightidle, видно буквально пару кадров от нужной анимации. Подозреваю, что это из-за условий выполнения анимации, ведь когда персонаж находится без опоры под ногами (прыгает или падает, то есть isGrounded = false) то анимация прекрасно проигрывается и не заменяется. Как можно исправить ситуацию? Заранее спасибо за уделенное время.
Как выполнить настройку анимированной модели персонажа в Unity3D?
Наверняка многим кажется достаточно сложным процесс создания и введения в проект анимированной модели персонажа. В этой статье мы хотим затронуть тему импорта 3D модели персонажа в Unity3D, его подготовку, импорт анимаций, настройку аниматора и простейший контроллер, который будет управлять движениями и анимацией персонажа.

И импортируем в проект:

Открываем в окне Project папку с персонажем, находим его модель, переносим в сцену.

Поскольку это модель из магазина AssetStore, она полностью настроена и готова к введению в игру. Тем не менее, важно убедиться, что всё настроено верно:
- Во вкладке Rig должен быть выбран AnimationType: Humanoid

2. Во вкладке Animation у данной модели нет собственных анимационных клипов. Именно поэтому мы возьмем их с сайта mixamo.com:

Эти анимации можно свободно скачать, что мы и сделаем сейчас.
Humanoid – анимации легко можно использовать на любых Humanoid – персонажах. Поэтому не важно, создадите ли Вы свою анимацию или скачаете готовую – любой из вариантов будет работать с Humanoid – персонажем.
Я подготовил вот такой сет анимаций. Он включает в себя:
- Holding Idle – анимация “стоим на месте”
- Walking – “Идем вперед”
- Walking Backward – “Идем назад”
- Walk Right и Walk Left – “Идем влево/вправо”
- Running, Left Run, Right Run – “Бег вперед, влево, вправо”.

Обязательно выберите все файлы с анимациями и во вкладке Rig переключите их в режим Humanoid:

Пора настроить импорт каждой анимации в проект. Выделяем,например, walking и переходим во вкладку Animation:

1.Назначаем ключи старта и окончания анимации (поскольку каждый файл анимации идет отдельным файлом, обычно эти ключи автоматически стоят верно).
- Присваиваем имя анимации, можно назвать так же, как мы назвали файлы.

3.Устанавливаем галочку LoopTime- этот включенный параметр зацикливает анимацию при воспроизведении.

Аналогичным образом настраиваем остальные анимации. Не забываем нажимать Apply для того чтобы применить все изменения анимационного клипа.

Теперь в сцене выделим персонажа. Давайте посмотрим на компонент Animator, который присутствует на нем. Нам важны два поля:

- Avatar – определяет, как именно будут связаны кости модели с костями в анимации. При импорте модели персонажа, движок автоматически создает аватар. Но если что-то идет не по плану, аватар можно сконфигурировать вручную. Для этого нужно выбрать модель персонажа в окне проекта, и во вкладке Rig перейти в Configure.

Если Вы всё делаете, как и я – проблем с аватаром возникнуть не должно.
2. Controller – Это то, с чем мы и будем работать дальше. Анимационный контроллер – это своего рода схема, в которой мы определим, как именно воспроизводятся анимации, в каком состоянии какие из анимаций смешиваются друг с другом. Если сказать проще, то именно в контроллер мы будем отправлять сигнал о том, какая анимация должна воспроизводиться в данный момент. Но обо всём по порядку.
Давайте создадим анимационный контроллер: Правой кнопкой мыши кликаем в окне проекта. Create – Animator Controller.

Получится вот такой файл, я назвал его PersonAnimatorController:

Кликаем по нему дважды, откроется вкладка Animator:

Это и есть окно, в котором мы установим алгоритм работы наших анимаций. Давайте сразу создадим 3 состояния (ПКМ – Create State – Empty):


Выделив одно из состояний (например, idle), в окне Inspector мы можем заметить, что поле Motion сейчас пустое. Сюда необходимо поместить анимационный клип (тот, которому мы настраивали ключи Start-End, устанавливали Loop pose, и т.д.).
Поэтому, не снимая выделение с выделенного элемента, в окне Project находим файл с анимацией Idle, и из него перетаскиваем АНИМАЦИОННЫЙ КЛИП в поле Motion в окне инспектора.

Таким же образом устанавливаем клипы в остальные состояния (walk, run).
Теперь в левой части окна Animator переходим во вкладку Parameters:


Создаем Int – параметр, назовем его “state”. Это переменная, которая будет определять, в каком состоянии сейчас находится аниматор персонажа (какое из наших трёх состояний воспроизводится в данный момент). Этим параметром в будущем мы будем управлять из скрипта.

Теперь необходимо создать переходы между состояниями.
Кликаем на Idle правой кнопкой, жмем на Make Transition, после чего наводим курсор на состояние Walk.


Сразу сделаем переходы между всеми состояниями, и туда, и обратно.

Теперь переходим к настройке каждого перехода. Первый переход:

Выделяем его, смотрим в правую часть окна Animator:

Has Exit Time – снимаем галочку. Этот параметр, при включенном состоянии, сначала ждет, пока текущая анимация отыграет полностью, а уже после – совершает переход в другое состояние. Нам это не нужно, т.к. переходы у нас будут в конкретные моменты, когда наша переменная state меняет своё значение.
В Conditions добавляем условие перехода:

Дословно это выглядит так: “Если state = 0”. Если представить это в виде кода:
То есть, выбранный переход сработает в том случае, когда значение state будет равно “1”.
Обратный переход из Walk в Idle настраиваем так (не забываем во всех переходах отключать Has Exit Time):

По аналогии, нужно сделать переходы:
Idle – Run (state equals 2)
Run – Idle (state equals 0)
Walk – run (state equals 2)
Run – Walk (state equals 1)
Не забудьте выделить персонажа в сцене и переместить созданный анимационный контроллер в поле Controller в компоненте Animator:

Теперь, если запустить игру и, выделив персонажа, в окне аниматора поменять значение state, мы увидим, что анимации воспроизводятся:
Вы можете заметить, что персонаж немного смещается и разворачивается. Это происходит, потому что мы не настроили смещение и поворот за счёт анимации. Делается это в окне импорта каждого файла анимации, во вкладке Animation. Обычно я настраиваю анимации так, чтобы они никак не влияли на перемещение или поворот. Установите флажок во всех опциях Bake Into Pose.
А так же Based Upon в Original.


Теперь создадим скрипт, чтобы управлять анимациями персонажа по нажатию на клавиши.


Называем его PersonController. Перетяните скрипт на персонажа, чтобы он отобразился в списке компонентов под компонентом Animator:

Открываем скрипт. Пишем код:

Теперь, если запустить игру, персонаж начнет реагировать на нажатия на клавиши.
На этом пока всё. Это базовый механизм настройки персонажа, аниматора, и простой способ воспроизвести анимации. На основе этого принципа можно анимировать многие игровые объекты, не только персонажей. Но для того, чтобы сделать качественное смешивание анимаций и не превратить Анимационный контроллер в мешанину из огромной кучи состояний и переменных, которыми сложно управлять, когда их много – существуют очень удобные инструменты смешивания в Animator (BlendTree), а так же возможность создать машину состояний внутри одного состояния. Но об мы расскажем в отдельной статье.
How to stop playing the first animation and start the second one (Unity)
I have two animations. Punch animation and kick animation. I set up an Animator to transition between animations. If the first animation is playing, I want to interrupt it and start playing the second animation without waiting for the first one to finish. To enable animations, I use triggers. For example, a character makes a punch, and then immediately kicks. I’ve tried using boolean variables, but I’m unable to abruptly end the animation and jump to the next one. How to set up an animator?
asked Aug 10 at 11:32
29 5 5 bronze badges
remove has exit time and check interruption source.
Aug 10 at 11:48
@BugFinder I think the interruption source is rather for interrupting the transition itself. The disabling of has exit time should be enough
Aug 10 at 12:25
possibly but its worth looknig at to see if it makes a difference.. if it doesnt we know better? 🙂
Aug 10 at 12:27
Would be better if OP posted more context; Some screenshots of the inspector setup, and the codes on how the interrupt is done. Eitherway, BugFinder’s solution is worth a try.