Проблемы покадровой анимации в Unity и как их быстро решить
Покадровая анимация на спрайтах в Unity из коробки — это весело.
Весело, конечно же, из-за встроенного в Unity аниматора, который часто пытаются использовать с ней. В каком-то смысле он слишком умный. Он отлично подойдёт для костной анимации и вообще, чего угодно, но не для кадровой анимации. Даже если всё-таки создать контроллер, импортировать правильно ассеты и настроить правильно клипы, то встреча с этой гигантской стейт-машиной, которая вынуждает писать очень странную и не всегда вразумительную логику в скриптах всё равно неизбежна.
Давайте сразу очертим ряд проблем, которые хотелось бы решить:
сложный механизм клипов;
не менее сложный механизм транзакций;
- невозможность «подменять» спрайты для скинов или просто универсальных контроллеров.
Про это ужасно много разных видео и статей, но я расскажу про самый тривиальный способ написать свой «велосипед» анимации, которым обычно пользуюсь сам. Сразу скажу, что каких-то открытий тут не будет, это лишь занимательная заметка.
Хранение анимации
Прежде всего, нужно создать объект, который будет хранить кадры анимации. Ничего особо не придумывая, я создал предельно простой scriptable-объект.
Чтобы каждый раз не собирать спрайты по одному руками, я сделал не менее простой скрипт для создания скриптового объекта.
Теперь достаточно выделить несколько спрайтов, нажать правую кнопку мыши и выбрать Sprite Line. Всё предельно просто.
Осталось прикрутить это всё к самим объектам.
Аниматор
Создадим компонент, который будет устанавливать спрайты в SpriteRenderer. Я не буду расписывать каждый кусок кода — просто выложу на него ссылку, там достаточно много комментариев. Ещё там лежит кастомный инспектор для удобства. Тут выделю просто важные моменты.
Во-первых, я сделал переменную _revalidate, чтобы не слишком часто дёргать SpriteRenderer. Если этого не делать, скрипт будет постоянно обращаться к полю sprite и постоянно подгуружать связанные с полем объекты. Чтобы это возымело какой-то эффект, на сцене должно быть несколько тысяч спрайтов, но лично мне так спокойнее. Лично у меня на M1 при 10 тысячах спрайтов в редакторе _revalidate стало вопросом 20 FPS.
Во-вторых, спрайт задается в LateUpdate. Это довольно важная деталь, чтобы можно было спокойно менять параметры из других скриптов и не переживать, что Update нашего аниматора вызовется до этого момента.
Вообще, аниматор получился ужасно простым, и его легко доделывать под нужные вещи. Я, например, добавил ивент для окончания анимации, чтобы разрушать объекты, которые представляют просто эффекты. Выглядит в редакторе это тоже максимально простенько, но ведь не часто нужно что-то большее.
Велосипеды — это плохо
Очевидно, что не всем нравится писать «велосипеды», и хочется что-то поддерживаемое. Относительно недавно (полгода как не в эксперименте, если быть точным) в Unity появился инструментарий для подмены спрайтов в клипах с поддержкой покадровой анимации. От аниматора уйти это не позволяет, но вводит инструментарий для всего, что описано выше. Если вам всё-таки нравится аниматор или просто тяжело с него слезать — это, возможно, ваш выбор.
Другой занимательный пример, который я видел, — это ReAnimator. Это довольно навороченный инструмент с поддержкой событий на кадры, синхронизации частоты кадров и хитрой системы переходов.
Очевидно, что тут в посте нет каких-то сакральных и неизвестных вещей. Тем не менее не все сразу отказываются от аниматора, видя множество туториалов с ним. Да и про его аналоги не всем известно. Так что, буду надеяться, эти заметки станут кому-то полезными в том или ином виде.