Использование AnimationTree

Введение

With AnimationPlayer, Godot has one of the most flexible animation systems that you can find in any game engine. The ability to animate almost any property in any node or resource, as well as having dedicated transform, bezier, function calling, audio and sub-animation tracks, is pretty much unique.

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

AnimationTree — это новый узел, представленный в Godot 3.1 для работы с продвинутыми переходами. Он заменяет древний AnimationTreePlayer, добавляя при этом гибкости и огромное количество функций.

Создание AnimationTree

Перед началом необходимо прояснить, что узел AnimationTree не содержит собственных анимаций. Вместо этого используется анимация, содержащаяся в узле AnimationPlayer. Таким образом, можно редактировать анимации (или импортировать их из сцены 3D) как обычно, а затем использовать этот дополнительный узел для управления воспроизведением.

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

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

Вот как это делается в демонстрации `Шутер от третьего лица <https ://github.com/godotengine/tps-demo >`_; для примера:

../../_images/animtree1.png

Для игрока была создана новая сцена с KinematicBody в качестве корня. Внутри этой сцены был инстанцирован оригинальный файл .dae (Collada) и создан узел AnimationTree.

Создание дерева

В AnimationTree можно использовать три основных типа узлов:

  1. Узлы анимации, которые ссылаются на анимацию из связанного AnimationTree.

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

  3. Узлы смешивания анимаций, которые используются в AnimationNaseBlendTree как смешение на одном и том же графике через несколько входных портов.

Для установки корневого узла в AnimationTree доступны несколько типов:

../../_images/animtree2.png
  • AnimationNiveAnimation: выбирает анимацию из списка и воспроизводит ее. Это простейший корневой узел, и он, обычно, не используется непосредственно как корневой.

  • AnimationNiveBlendTree: Содержит множество узлов типа blend, таких как mix, blend2, blend3, one shot и т. д. Это один из наиболее часто используемых корней.

  • AnimationNiveStateMachine: содержит несколько корневых узлов в качестве дочерних в графе. Каждый узел используется как state и предоставляет несколько функций для переходов между состояниями.

  • AnimationNodeBlendSpace2D: позволяет размещать корневые узлы в 2D пространстве смешения. Управляет смешением положений в 2D для смешивания нескольких анимаций.

  • AnimationNodeBlendSpace1D: Simplified version of the above (1D).

Дерево смешения

AnimationNaseBlendTree может содержать как корневые, так и обычные узлы, используемые для смешения. Узлы добавляются в граф из меню:

../../_images/animtree3.png

Все деревья смешения по умолчанию содержат узел «Output», и для воспроизведения анимации к нему необходимо что-то подключить.

Самый простой способ проверить эту функциональность — подключить к нему непосредственно узел Animation:

../../_images/animtree4.png

Это просто воспроизводит анимацию. Убедитесь, что AnimationTree активен, чтобы что-то действительно произошло.

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

Blend2 / Blend3

Эти узлы будут смешиваться между двумя или тремя входами по указанному пользователем значению смешения:

../../_images/animtree5.gif

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

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

../../_images/animtree6.png

OneShot

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

../../_images/animtree6b.gif

Seek

Этот узел может использоваться для выполнения команды seek с любыми нижестоящими элементами графа анимации. Этот тип узла используется для воспроизведения Animation с начальной или любой другой позиции воспроизведения внутри AnimationNaseBlendTree.

После установки времени и изменения воспроизведения анимации узел seek автоматически переходит в спящий режим на следующем кадре процесса, установив значение seek_position равным -1.0.

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

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

TimeScale

Позволяет масштабировать скорость анимации (или обращать ее) в любых дочерних узлах. Установка значения в 0 приостановит анимацию.

Transition

Очень простой конечный автомат (если, конечно, Вы не хотите возиться с узлом StateMachine). Анимация может быть подключена к выходам, и можно указать время перехода.

BlendSpace2D

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

../../_images/animtree7.gif

Координаты X и Y могут настраиваться (и маркироваться для удобства). По умолчанию точки можно размещать в любом месте (просто щелкните правой кнопкой мыши на системе координат, или используйте кнопку Добавить точку), и треугольники будут создаваться автоматически с помощью Delaunay.

../../_images/animtree8.gif

Можно также нарисовать треугольники вручную, отключив опцию auto triangle, хотя это требуется редко:

../../_images/animtree9.png

Наконец, можно изменить режим смешения. По умолчанию смешение происходит путем интерполяции точек внутри ближайшего треугольника. При работе с 2D анимациями (покадрово) можно переключиться в режим Дискретный. Кроме того, если требуется сохранить текущее положение воспроизведения при переключении между дискретными анимациями, используется режим Перенос. Этот режим можно изменить в меню Смешение:

../../_images/animtree10.png

BlendSpace1D

Это похоже на 2D пространства смешивания, но в одном измерении (поэтому треугольники не нужны).

StateMachine

This node acts as a state machine with root nodes as states. Root nodes can be created and connected via lines. States are connected via Transitions, which are connections with special properties. Transitions are uni-directional, but two can be used to connect in both directions.

../../_images/animtree11.gif

There are many types of transition:

../../_images/animtree12.png
  • Immediate: Немедленно перейдет в следующее состояние. Текущее состояние завершается и происходит переход в новое состояние.

  • Sync: Немедленно перейдет в следующее состояние, но будет установлено в позицию воспроизведения старого состояния.

  • At End: Дождется окончания воспроизведения текущего состояния, а затем переключится в начало анимации следующего состояния.

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

../../_images/animtree13.png
  • Switch Mode — тип перехода (см. выше), его можно изменить после создания здесь.

  • Auto Advance включит переход автоматически при достижении этого состояния. Это лучше всего подходит для режима переключения At End.

  • Advance Condition включит автоматический шаг при установке этого условия. Это настраиваемое текстовое поле, которое может быть заполнено именем переменной. Переменная может быть изменена из кода (подробнее об этом ниже).

  • Xfade Time - время перекрестного затухания между этим состоянием и следующим.

  • Priority is used together with the travel() function from code (more on this later). Lower priority transitions are preferred when travelling through the tree.

  • Disabled toggles disabling this transition (when disabled, it will not be used during travel or auto advance).

Root motion

When working with 3D animations, a popular technique is for animators to use the root skeleton bone to give motion to the rest of the skeleton. This allows animating characters in a way where steps actually match the floor below. It also allows precise interaction with objects during cinematics.

When playing back the animation in Godot, it is possible to select this bone as the root motion track. Doing so will cancel the bone transformation visually (the animation will stay in place).

../../_images/animtree14.png

Afterwards, the actual motion can be retrieved via the AnimationTree API as a transform:

anim_tree.get_root_motion_transform()

This can be fed to functions such as KinematicBody.move_and_slide to control the character movement.

There is also a tool node, RootMotionView, that can be placed in a scene and will act as a custom floor for your character and animations (this node is disabled by default during the game).

../../_images/animtree15.gif

Controlling from code

After building the tree and previewing it, the only question remaining is "How is all this controlled from code?".

Keep in mind that the animation nodes are just resources and, as such, they are shared between all instances using them. Setting values in the nodes directly will affect all instances of the scene that uses this AnimationTree. This is generally undesirable, but does have some cool use cases, e.g. you can copy and paste parts of your animation tree, or reuse nodes with a complex layout (such as a state machine or blend space) in different animation trees.

The actual animation data is contained in the AnimationTree node and is accessed via properties. Check the "Parameters" section of the AnimationTree node to see all the parameters that can be modified in real-time:

../../_images/animtree16.png

This is handy because it makes it possible to animate them from an AnimationPlayer, or even the AnimationTree itself, allowing the realization of very complex animation logic.

To modify these values from code, the property path must be obtained. This is done easily by hovering the mouse over any of the parameters:

../../_images/animtree17.png

Which allows setting them or reading them:

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

State machine travel

One of the nice features in Godot's StateMachine implementation is the ability to travel. The graph can be instructed to go from the current state to another one, while visiting all the intermediate ones. This is done via the A* algorithm. In the absence of any viable set of transitions starting at the current state and finishing at the destination state, the graph teleports to the destination state.

To use the travel ability, you should first retrieve the AnimationNodeStateMachinePlayback object from the AnimationTree node (it is exported as a property).

var state_machine = anim_tree["parameters/playback"]

Once retrieved, it can be used by calling one of the many functions it offers:

state_machine.travel("SomeState")

The state machine must be running before you can travel. Make sure to either call start() or choose a node to Autoplay on Load.

../../_images/animtree18.png