Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

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

Вступ

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

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

AnimationTree – це вузол, призначений для обробки складних переходів.

AnimationTree та AnimationPlayer

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

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

Ось як це зроблено в демо-версії шутера від третьої особи <https://godotengine.org/asset-library/asset/2710>`_, для довідки:

../../_images/animtree_treeandplayersetup.png

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

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

Щоб використовувати AnimationTree, потрібно встановити кореневий вузол. Кореневий вузол анімації — це клас, який містить та оцінює підвузли та виводить анімацію. Існує 3 типи підвузлів:

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

  2. Корені вузли анімації, які використовуються для поєднання підвузлів і можуть бути вкладеними.

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

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

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

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

  • AnimationNodeBlendSpace1D: Дозволяє лінійне змішування між двома вузлами анімації. Керуйте положенням змішування в 1D-просторі змішування для змішування між анімаціями.

  • AnimationNodeBlendSpace2D: Дозволяє лінійне змішування між трьома вузлами анімації. Керуйте положенням змішування у 2D-просторі змішування для змішування між анімаціями.

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

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

Коли ви створюєте AnimationNodeBlendTree, ви отримуєте порожній 2D-графік у нижній панелі, під вкладкою AnimationTree. За замовчуванням він містить лише вузол Output.

../../_images/animtree_emptyblendtree.webp

Для відтворення анімації вузол має бути підключений до виходу. Ви можете додати вузли з меню Додати вузол.. або клацнувши правою кнопкою миші на порожньому місці:

../../_images/animtree_blendnodes.webp

Найпростіше підключення — це підключити вузол Animation безпосередньо до виводу, який просто відтворюватиме анімацію.

../../_images/animtree_animtooutput.png

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

Blend2 / Blend3

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

../../_images/animtree_blend2.gif

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

../../_images/animtree_filtering.png

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

Одним махом

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

../../_images/animtree_oneshot.gif
# Play child animation connected to "shot" port.
animation_tree.set("parameters/OneShot/request", AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE)
# Alternative syntax (same result).
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).
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).
animation_tree["parameters/OneShot/active"]

Часова Шкал

Цей вузол дозволяє вам перейти до певного моменту часу в анімації, підключеного до його входу in. Використовуйте цей вузол для відтворення анімації, починаючи з певної позиції відтворення. Зверніть увагу, що значення запиту на пошук вимірюється в секундах, тому, якщо ви хочете відтворити анімацію з початку, встановіть значення 0.0, або якщо ви хочете відтворити анімацію з 3 секунд, встановіть значення 3.0.

../../_images/animtree_timeseek.webp
# Play child animation from the start.
animation_tree.set("parameters/TimeSeek/seek_request", 0.0)
# Alternative syntax (same result).
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).
animation_tree["parameters/TimeSeek/seek_request"] = 12.0

ЧасоваШкала

Цей вузол дозволяє масштабувати швидкість анімації, підключеної до його входу in. Швидкість анімації буде помножена на число в параметрі scale. Встановлення масштабу на 0 призупинить анімацію. Встановлення масштабу на від'ємне число призведе до відтворення анімації у зворотному порядку.

../../_images/animtree_timescale.webp

Перехід

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

../../_images/animtree_transition.webp
# Play child animation connected to "state_2" port.
animation_tree.set("parameters/Transition/transition_request", "state_2")
# Alternative syntax (same result).
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).
animation_tree["parameters/Transition/current_state"]

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

Машина стану

Коли ви створюєте AnimationNodeStateMachine, ви отримуєте порожній 2D-графік у нижній панелі, на вкладці AnimationTree. Він за замовчуванням містить стани Start та End.

../../_images/animtree_emptystatemachine.webp

Щоб додати стани, клацніть правою кнопкою миші або скористайтеся кнопкою створити нові вузли, значок якої є плюсом у квадратику. Ви можете додавати анімації, простори змішування, дерева змішування або навіть інший StateMachine. Щоб редагувати один із цих складніших підвузлів, натисніть на значок олівця праворуч від стану. Щоб повернутися до початкового StateMachine, натисніть Корінь у верхньому лівому куті панелі.

Перш ніж StateMachine зможе виконати будь-які корисні дії, стани мають бути з'єднані переходами. Щоб додати перехід, натисніть кнопку з'єднати вузли, яка являє собою лінію зі стрілкою, спрямованою праворуч, і перетягніть вказівник між двома станами. Ви можете створити 2 переходи між станами, по одному в кожному напрямку.

../../_images/animtree_connections.gif

Існує 3 типи переходів:

../../_images/animtree_transitiontypes.png
  • Негайно: Перехід до наступного стану відбудеться негайно.

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

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

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

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

  • Кривава Xfade — це перехресне перетворення, що відповідає кривій, а не лінійне змішування.

  • Скидання визначає, чи стан, у який ви перемикаєтеся, відтворюється з початку (true) чи ні (false).

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

  • Режим перемикання – це тип переходу (див. вище). Його можна змінити після створення тут.

  • Режим просування визначає режим просування. Якщо Вимкнено, перехід не використовуватиметься. Якщо Увімкнено, перехід використовуватиметься лише під час travel(). Якщо Автоматично, перехід використовуватиметься, якщо умова просування та вираз істинні, або якщо немає умов/виразів просування.

Умова попереднього рівня та вираз попереднього рівня

Останні 2 властивості переходу StateMachine - це Advance Condition та Advance Expression. Коли для режиму просування встановлено значення Auto, вони визначають, чи буде перехід просуватися чи ні.

Попередня умова перевіряє значення «істина»/«хибність». Ви можете ввести назву користувацької змінної в текстове поле, і коли StateMachine досягне цього переходу, він перевірить, чи є ваша змінна істинною. Якщо так, перехід продовжується. Зверніть увагу, що попередня умова перевіряє лише, чи є змінна істинною, і не може перевіряти значення «хибність».

Це надає Умові Випередження дуже обмежені можливості. Якби ви хотіли зробити перехід туди-сюди на основі однієї властивості, вам потрібно було б створити 2 змінні з протилежними значеннями та перевірити, чи є будь-яка з них істинною. Саме тому в Godot 4 було додано Вираз Випередження.

Вираз Advance працює подібно до умови Advance, але замість перевірки, чи є одна змінна істинною, він обчислює будь-який вираз. Вираз — це все, що можна помістити в оператор if. Ось приклади виразів, які працюватимуть у виразі Advance:

  • is_walking

  • is_walking == true (поводиться так само, як і вищезгадане)

  • is_walking && !is_idle

  • velocity > 0

  • player.is_on_floor()

Попередження

Вираз чутливий до регістру. Якщо ви посилаєтеся на властивості движка, такі як velocity, на вузлі CharacterBody3D, вам слід використовувати правила іменування snake_case. Якщо ви посилаєтеся на властивості скрипта, вам слід відповідати стилю, що використовується у скрипті, який зазвичай є snake_case у GDScript та PascalCase у C#.

Ось приклад неправильно налаштованого переходу StateMachine з використанням Advance Condition:

../../_images/animtree_badanimcondition.webp ../../_images/animtree_badanimcondition.gif

Це не працює, оскільки в умові Advance є змінна !, яку неможливо перевірити.

Ось той самий приклад, налаштований правильно, з використанням двох протилежних змінних:

../../_images/animtree_goodanimcondition.webp ../../_images/animtree_goodanimcondition.gif

Ось той самий приклад, але з використанням попереднього виразу, а не попередньої умови, що усуває необхідність у двох змінних:

../../_images/animtree_goodanimexpression.webp ../../_images/animtree_goodanimexpression2.webp ../../_images/animtree_goodanimexpression.gif

Щоб використовувати розширені вирази (Advance Expressions), необхідно встановити базовий вузол Advance Expression з інспектора вузла AnimationTree. За замовчуванням він встановлений на сам вузол AnimationTree, але має вказувати на будь-який вузол, що містить скрипт із вашими змінними анімації.

Дивись також

Вираз Advance обчислюється за допомогою класу Godot Expression. Див. Обчислення виразів для отримання додаткової інформації про написання виразів.

Подорожі StateMachine

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

Щоб скористатися можливістю подорожувати, спочатку слід отримати об'єкт AnimationNodeStateMachinePlayback з вузла AnimationTree (він експортується як властивість), а потім викликати одну з його численних функцій:

var state_machine = animation_tree["parameters/playback"]
state_machine.travel("SomeState")

Перш ніж ви зможете подорожувати, StateMachine має бути запущено. Обов'язково викличте start() або підключіть вузол до Start.

BlendSpace2D та BlendSpace1D

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

../../_images/animtree_blendspace2d.gif

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

../../_images/animtree_blendspacepoints.gif

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

../../_images/animtree_blendmode.png

BlendSpace1D працює так само, як BlendSpace2D, але в одному вимірі (лінії). Трикутники не використовуються.

../../_images/animtree_blendspace1d.webp

Sync mode

Both BlendSpace1D and BlendSpace2D have a Sync Mode property that controls how animations advance when they are blended. This replaces the older boolean sync property and offers more precise control.

../../_images/animtree_syncmode_mutable.webp

There are four modes available:

  • None (default): Inactive animations are frozen and do not advance. Only the currently active (highest-weight) animation moves forward.

  • Independent: Inactive animations advance with a weight of 0. This matches the behavior of the old sync = true setting.

  • Cyclic Mutable: All animations are time-scaled so their phases stay aligned. The shared cycle length is computed dynamically from the active blend weights, which means a single unblended animation plays at its normal speed. This is useful when all your animations have the same logical cycle (e.g. locomotion loops) but may differ slightly in length.

  • Cyclic Constant: All animations are time-scaled to complete one full cycle in exactly Cyclic Length seconds, regardless of their individual lengths. Set the cyclic_length property to your desired cycle duration (must be greater than 0).

Попередження

Cyclic sync modes require that all blend points use AnimationNodeAnimation with a finite, immutable length. If any blend point uses a different node type, a warning will be shown and cyclic sync will not take effect:

../../_images/animtree_syncmode_warning.webp

Примітка

When using either cyclic mode with animations of different lengths, applying an AnimationNodeTimeSeek to the output will break synchronization. In that case, use AnimationNodeAnimation.use_custom_timeline to normalize animation lengths before syncing.

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

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

Якщо для кісток 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/animtree_rootmotiontrack.webp

Після цього фактичний рух можна отримати через 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. Зазвичай це небажано, але має кілька цікавих варіантів використання, наприклад, ви можете копіювати та вставляти частини вашого дерева анімації або повторно використовувати вузли зі складним макетом (наприклад, StateMachine або простір змішування) в різних деревах анімації.

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

../../_images/animtree_parameters.webp

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

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

../../_images/animtree_propertypath.webp

Тоді ви можете встановити або прочитати їх:

animation_tree.set("parameters/eye_blend/blend_amount", 1.0)
# Alternate syntax (same result)
animation_tree["parameters/eye_blend/blend_amount"] = 1.0

Примітка

Розширені вирази з машини станів не будуть знайдені в параметрах. Це тому, що вони зберігаються в іншому скрипті, а не в самому дереві анімації. Розширені Умови будуть знайдені в параметрах.