Эта страница смотрится лучше со включённым JavaScript

Нюансы работы Animator в Unity, и как с ними жить.

 ·  ☕ 2 min read

Читал давеча документацию к Animancer и внезапно для себя обнаружил, что двойной костыль из моего кода - это не костыль вовсе, а рекомендованное написание кода при работе с анимациями в Unity.

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

  1. Определяется, сколько врагов сгенерирует портал.
  2. Портал играет анимацию открытия.
  3. Портал играет первую половину анимации “Свечения/Glow”.
  4. Возле портала появляется очередной враг.
  5. Портал играет вторую половину анимации “Свечения/Glow”.
  6. Если все враги сгенерировались, то играется анимация закрытия портала. Иначе повторяется пункт 3 и последующие.

Реализация этого алгоритма сделана через корутины, и для правильного определения задержек, используется код:

1
2
PortalAnimator.Play(RAnimations.PortalGlow);
duration = PortalAnimator.GetCurrentAnimatorStateInfo(0).length;

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

Так вот работало всё криво и косо: то анимации пропускались, то враги генерились с неправильными интервалами. Помогло обращение к форумам, где иногда встречается совет дождаться конца кадра или пропустить кадр. Например, тут EvilWarren пишет об этом.

Второй нюанс связан с тем, что аниматор получив один вызов Play будет игнорировать все последующие, сделанные в том же кадре. Скорее всего, я огрёб и от этого тоже. После применения советов с форумов порталы заработали, а код стал выглядеть “криво и косо”.

1
2
3
4
5
animatedRoomPortal.PlayAnimation(RAnimations.Dummy);
yield return null;
PortalAnimator.Play(RAnimations.PortalGlow);
yield return null;
duration = PortalAnimator.GetCurrentAnimatorStateInfo(0).length;

Здесь запуск Dummy анимации может и не нужен, а остался с предыдущих экспериментов, когда анимация PortalGlow не хотела запускаться два раза подряд.

Выводы:
  1. Если вы запускаете анимацию, а она не играется, - это норма. Подождите кадр перед запуском.
  2. Если вам надо узнать продолжительность анимации, то после запуска подождите кадр и только после этого обращайтесь к Animator.GetCurrentAnimatorStateInfo(0).length.
  3. Может игра и без анимаций выглядит ничё так.

Подробнее можно почитать в вышеупомянутой документации к Animancer. Там и другие недостатки анимационной системы описаны, есть о чём задуматься.

Share on