Використання Дерева анімації

Вступ

Завдяки AnimationPlayer анімаційна система Godot є одною з найбільш гнучких серед ігрових рушіїв. Можливість анімувати майже будь-яку властивість будь-якого вузла, або ресурсу, а також мати виділені перетворення, криві Безьє, виклики методів, аудіо- та під-анімаційні доріжки, є майже унікальною.

Однак підтримка змішування цих анімацій в AnimationPlayer відносно обмежена, оскільки можна встановити лише фіксований час плавного переходу.

Створення Дерева Анімацій

Спочатку необхідно чітко зрозуміти, що вузол AnimationTree не містить власних анімацій. Замість цього він використовує анімацію, що міститься в вузлі AnimationPlayer. Таким чином, ви можете редагувати свої анімації (або імпортувати їх з 3D-сцени), як зазвичай, а потім використовувати цей додатковий вузол для управління відтворенням.

Найчастіше AnimationTree використовують в 3D-сценах. Імпортовані сцени, як правило, поставляються із вбудованою анімацією (або кількома, або розділеною при імпорті одною великою). В кінці імпортована сцена Godot буде містити анімацію в вузлі AnimationPlayer.

Оскільки ви нечасто використовуєте імпортовані сцени безпосередньо в Godot (вони або вставляються, як екземпляри, або успадковуються), ви можете розмістити вузол AnimationTree у новій сцені, яка містить імпортовану. Після цього вкажіть вузлу AnimationTree вузол AnimationPlayer, що був створений в імпортованій сцені.

Ось як це зроблено в демонстрації стрілялки від третьої особи:

../../_images/animtree1.png

Було створено нову сцену для гравця з CharacterBody3D як root. Усередині цієї сцени було створено оригінальний файл .dae (Collada) і створено вузол AnimationTree.

Створення дерева

Існує три основних типи вузлів, які можна використовувати в AnimationTree:

  1. Вузли анімації, які посилаються на анімацію зі зв’язаного AnimationPlayer.

  2. Анімаційні кореневі вузли, які використовуються для змішування під-вузлів.

  3. Вузли анімації Blend, які використовуються в AnimationNodeBlendTree як один графік змішування з кількох вхідних портів.

Доступні кілька типів кореневих вузлів у AnimationTree:

../../_images/animtree2.png
  • AnimationNodeAnimation: Вибирає анімацію зі списку та відтворює її. Це найпростіший кореневий вузол, і, як правило, не використовується безпосередньо як корінь.

  • AnimationNodeBlendTree: Містить багато вузлів з типом змішування, таких як mix, blend2, blend3, one shot, тощо. Це один з найбільш часто використовуваних коренів.

  • AnimationNodeStateMachine: Містить кілька кореневих вузлів, як дочірніх, на графіку. Кожен вузол використовується як стан і надає кілька функцій для чергування між станами.

  • AnimationNodeBlendSpace2D: Дозволяє розміщувати кореневі вузли в просторі 2D змішування. Керуйте позицією накладання в 2D, щоб змішувати кілька анімацій.

  • AnimationNodeBlendSpace1D: Спрощена версія вищенаведеного (1D).

Дерево змішування

AnimationNodeBlendTree може містити як кореневі, так і звичайні вузли, які використовуються для змішування. Вузли додаються до графіка з меню:

../../_images/animtree3.webp

Всі дерева суміші за замовчуванням містять вузол Output (Вивід), і до нього потрібно підключити щось, щоб анімація відтворювалася.

Найпростіший спосіб протестувати цю функціональність - підключити безпосередньо до нього вузол Animation:

../../_images/animtree4.png

Це просто відтворить анімацію. Для того, щоб щось сталося AnimationTree має бути активним.

Нижче наведено короткий опис доступних вузлів:

Blend2 / Blend3

Ці вузли будуть змішувати два, або три, входи за вказаним користувачем значенням змішування:

../../_images/animtree5.gif

Для складнішого змішування рекомендується замість цього використовувати простір для змішування.

При змішуванні також можна використовувати фільтри, тобто ви можете індивідуально контролювати, які доріжки проходять через функцію змішування. Це дуже корисно для накладання анімацій одної на одну.

../../_images/animtree6.png

Одним махом

Цей вузол виконує допоміжну анімацію, а потім повертається до основної. Час сповільнення та прискорення змішування можна налаштувати, як і фільтри.

../../_images/animtree6b.gif

Після встановлення запиту та зміни відтворення анімації одноразовий вузол автоматично очищає запит у наступному кадрі процесу, встановлюючи для свого запиту значення AnimationNodeOneShot.ONE_SHOT_REQUEST_NONE.

# Play child animation connected to "shot" port.
animation_tree.set("parameters/OneShot/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE)
# Alternative syntax (same result as above).
animation_tree["parameters/OneShot/request"] = AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE

# Abort child animation connected to "shot" port.
animation_tree.set("parameters/OneShot/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_ABORT)
# Alternative syntax (same result as above).
animation_tree["parameters/OneShot/request"] = AnimationNodeOneShot.ONE_SHOT_REQUEST_ABORT

# Get current state (read-only).
animation_tree.get("parameters/OneShot/active"))
# Alternative syntax (same result as above).
animation_tree["parameters/OneShot/active"]

Часова Шкал

Цей вузол може бути використаний для команди пошуку будь-яких допоміжних нащадків з анімаційного графіка. Цей тип вузла використовується для відтворення Animation з самого початку, або певної позиції, всередині AnimationNodeBlendTree.

Після встановлення часу та зміни відтворення анімації вузол пошуку автоматично переходить у режим сну на наступному кадрі процесу, встановлюючи значення seek_request на -1.0.

# Play child animation from the start.
animation_tree.set("parameters/TimeSeek/seek_request", 0.0)
# Alternative syntax (same result as above).
animation_tree["parameters/TimeSeek/seek_request"] = 0.0

# Play child animation from 12 second timestamp.
animation_tree.set("parameters/TimeSeek/seek_request", 12.0)
# Alternative syntax (same result as above).
animation_tree["parameters/TimeSeek/seek_request"] = 12.0

ЧасоваШкала

Дозволяє масштабувати швидкість анімації (або повертати її), підключеної до входу in через параметр scale. Встановлення параметра «масштаб» на 0 призупинить анімацію.

Перехід

Дуже простий кінцевий автомат (якщо ви не хочете мати справу з вузлом StateMachine). До виходів можна підключити анімацію та вказати час переходу. Після встановлення запиту та зміни відтворення анімації вузол переходу автоматично очищає запит у наступному кадрі процесу, встановлюючи для свого значення transition_request значення порожнього рядка.

# Play child animation connected to "state_2" port.
animation_tree.set("parameters/Transition/transition_request", "state_2")
# Alternative syntax (same result as above).
animation_tree["parameters/Transition/transition_request"] = "state_2"

# Get current state name (read-only).
animation_tree.get("parameters/Transition/current_state")
# Alternative syntax (same result as above).
animation_tree["parameters/Transition/current_state"]

# Get current state index (read-only).
animation_tree.get("parameters/Transition/current_index"))
# Alternative syntax (same result as above).
animation_tree["parameters/Transition/current_index"]

Blend Простір 2D

BlendSpace2D — це вузол для розширеного змішування у двох вимірах. Точки додаються до двовимірного простору, а потім положення можна контролювати, щоб визначити накладання:

../../_images/animtree7.gif

Діапазонами в X і Y можна керувати (і позначати їх для зручності). За замовчуванням точки можна розміщувати будь-де (клацніть правою кнопкою миші на системі координат або скористайтеся кнопкою додати точку), а трикутники будуть створені автоматично за допомогою Делоне.

../../_images/animtree8.gif

Також можна намалювати трикутники вручну, відключивши опцію автоматичного трикутника, хоча це нечасто буває необхідним:

../../_images/animtree9.png

Нарешті, можна змінити режим змішування. За замовчуванням змішування відбувається шляхом інтерполяції точок всередині найближчого трикутника. Коли ви маєте справу з 2D-анімацією (кадр за кадром), ви можете перейти в дискретний режим. Крім того, якщо ви хочете зберегти поточну позицію відтворення під час перемикання між дискретними анімаціями, існує режим Carry. Цей режим можна змінити в меню Змішувати:

../../_images/animtree10.png

Blend Простір 1D

Це схоже на простори 2D-змішування, але в одному вимірі (тому трикутники не потрібні).

Машина стану

Цей вузол діє як машина станів з кореневими вузлами як станами. Кореневі вузли можуть створюватися і з'єднуватися по лініях. Стани з'єднуються через Переходи, які є з'єднаннями зі спеціальними властивостями. Переходи є однонаправленими, але два можуть бути використані для з'єднання в обох напрямках.

../../_images/animtree11.gif

Є багато типів переходів:

../../_images/animtree12.png
  • Негайно: Негайний перехід до наступного стану. Поточний стан завершиться і почнеться новий.

  • Синхронізувати: Переключиться на наступний стан негайно, але буде шукати новий стан до позиції відтворення старого стану.

  • На кінець: Чекатиме завершення відтворення поточного стану, а потім переключиться на початок анімації наступної стану.

Переходи також мають кілька властивостей. Натисніть будь-який перехід, і вони будуть відображатися на панелі інспектора:

../../_images/animtree13.png
  • Switch Mode- це тип переходу (див. вище), його можна змінити після створення тут.

  • Auto Advance ввімкне автоматичний перехід, коли цей стан буде досягнуто. Найкраще працює з режимом перемикача На кінець.

  • Advance Condition ввімкне автоматичне просування вперед, коли буде встановлено цю умову. Це настроюване текстове поле, яке можна заповнити ім'ям змінної. Змінну можна змінити з коду (докладніше про це пізніше).

  • Xfade Time - це час, щоб переходу між цим станом і наступним.

  • Priority використовується разом з функцією travel() з коду (докладніше про це пізніше). Переходи з нижчим пріоритетом мають перевагу під час переходу по дереву.

  • Disabled дозволяє відключити цей перехід (він не буде використовуватися під час переходів, чи автоматичного просування).

Для кращого змішування

У Godot 4.0+, щоб результати змішування були детермінованими (відтворюваними та завжди узгодженими), значення змішаних властивостей повинні мати певне початкове значення. Наприклад, у випадку двох анімацій, які потрібно змішати, якщо одна анімація має доріжку властивостей, а інша — ні, змішана анімація обчислюється так, якби остання анімація мала доріжку властивостей із початковим значенням.

Якщо для кісток Skeleton3D використовуються 3D-треки позиції/обертання/масштабу, початковим значенням є Bone Rest. Для інших властивостей початкове значення дорівнює 0, і якщо трек присутній в анімації RESET, замість нього використовується значення його першого ключового кадру.

Наприклад, наступний програвач AnimationPlayer має дві анімації, але в одній із них відсутній трек властивостей для позиції.

../../_images/blending1.webp

Це означає, що бракує анімації, яка розглядатиме ці позиції як Вектор2(0, 0).

../../_images/blending2.webp

Цю проблему можна вирішити, додавши доріжку властивостей для Position як початкове значення до анімації RESET.

../../_images/blending3.webp ../../_images/blending4.webp

Примітка

Майте на увазі, що існує анімація RESET для визначення стандартної пози під час початкового завантаження об’єкта. Передбачається, що він має лише один кадр і не очікується, що він буде відтворюватися за допомогою шкали часу.

Також пам’ятайте, що доріжки «Обертання 3D» і «Доріжки властивостей» для 2D-обертання з параметром «Тип інтерполяції» на «Лінійний кут» або «Кубічний кут» запобігатимуть обертанню більш ніж на 180 градусів від початкового значення у вигляді змішаної анімації.

Це може бути корисним для Skeleton3D, щоб запобігти проникненню кісток у тіло під час змішування анімацій. Таким чином, значення Bone Rest у Skeleton3D повинні бути якомога ближче до середини діапазону переміщення. Це означає, що для гуманоїдних моделей бажано імпортувати їх у Т-позі.

../../_images/blending5.webp

Ви бачите, що найкоротший шлях обертання з Bone Rest має пріоритет, а не найкоротший шлях обертання між анімаціями.

Якщо вам потрібно повернути сам Skeleton3D більш ніж на 180 градусів за допомогою змішування анімації для руху, ви можете використовувати Root Motion.

Рух кореня

При роботі з 3D-анімацією популярна техніка полягає в тому, щоб аніматори використовували кореневу кістку скелета, щоб рухати увесь скелет. Це дозволяє анімувати персонажі таким чином, щоб кроки справді відповідали підлозі нижче. Це також дозволяє точно взаємодіяти з об'єктами під час кінематографії.

Під час відтворення анімації в Godot можна вибрати цю кістку як доріжку руху кореня. Це скасує візуальне перетворення кісток (анімація залишиться на місці).

../../_images/animtree14.png

Після цього фактичний рух можна отримати через API AnimationTree, як перетворення:

# Get the motion delta.
animation_tree.get_root_motion_position()
animation_tree.get_root_motion_rotation()
animation_tree.get_root_motion_scale()

# Get the actual blended value of the animation.
animation_tree.get_root_motion_position_accumulator()
animation_tree.get_root_motion_rotation_accumulator()
animation_tree.get_root_motion_scale_accumulator()

Це можна передати таким функціям, як CharacterBody3D.move_and_slide для керування рухом персонажа.

Існує також вузол інструменту RootMotionView, який може бути розміщений на сцені і виступати в якості спеціальної підлоги для вашого персонажа та анімації (цей вузол за замовчуванням вимикається під час гри).

../../_images/animtree15.gif

Контроль з коду

Після побудови дерева та його попереднього перегляду залишилося єдине питання: "Як все це контролюється з коду?".

Майте на увазі, що анімаційні вузли є лише ресурсами і, таким чином, вони поділяються між усіма екземплярами. Встановлення значень у вузлах безпосередньо вплине на всі екземпляри сцени, яка використовує це Дерево Анімації AnimationTree. Загалом це не бажано, однак є деякі круті випадки для використання, наприклад, ви можете копіювати та вставляти частини дерева анімації, або повторно використовувати вузли зі складним макетом (наприклад, машина станів, або простір для змішування) у різних анімаційних деревах.

Фактичні дані анімації містяться в вузлі AnimationTree і доступні за допомогою властивостей. Перевірте розділ вузла Parameters, щоб побачити всі параметри, які можна змінити в режимі реального часу:

../../_images/animtree16.png

Це зручно, тому що це дає можливість анімувати їх з``AnimationPlayer`` , або навіть самого AnimationTree, що дозволяє реалізувати дуже складну логіку анімації.

Щоб змінити ці значення з коду, потрібно отримати шлях властивості. Для цього досить навести курсор мишки на будь-який з параметрів:

../../_images/animtree17.png

Маючи шлях можна встановлювати їх, або читати:

animation_tree.set("parameters/eye_blend/blend_amount", 1.0)
# Simpler alternative form:
animation_tree["parameters/eye_blend/blend_amount"] = 1.0

Переходи машини станів

Однією з приємних особливостей у реалізації StateMachine від Godot є можливість подорожувати. Графу можна дати вказівку переходити з поточного стану в інший, відвідуючи всі проміжні. Це робиться за допомогою алгоритму A*. Якщо немає шляху переходів, починаючи з поточного стану і закінчуючи станом призначення, графік телепортується до стану призначення.

Щоб скористатися переходами, слід спочатку отримати об'єкт AnimationNodeStateMachinePlayback з вузла AnimationTree (він експортується як властивість).

var state_machine = animation_tree["parameters/playback"]

Після отримання його можна використовувати, викликавши одну з багатьох функцій, які він пропонує:

state_machine.travel("SomeState")

Державна машина повинна спочатку запуститися перед відтворенням переходів. Обов'язково викличте start(), або виберіть на вузлі Autoplay on Load.

../../_images/animtree18.png