Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Использование дерева анимации

Введение

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

A new scene was created for the player with a CharacterBody3D as root. Inside this scene, the original .dae (Collada) file was instantiated and an AnimationTree node was created.

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

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

  1. Animation nodes, which reference an animation from the linked AnimationPlayer.

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

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

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

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

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

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

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

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

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

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

../../_images/animtree3.webp

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

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

../../_images/animtree4.png

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

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

Blend2 / Blеnd3

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

../../_images/animtree5.gif

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

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

../../_images/animtree6.png

OneShоt

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

../../_images/animtree6b.gif

After setting the request and changing the animation playback, the one-shot node automatically clears the request on the next process frame by setting its request value to 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"]

TimeSeek

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

After setting the time and changing the animation playback, the seek node automatically goes into sleep mode on the next process frame by setting its seek_request value to -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

TimeScаle

Allows scaling the speed of the animation (or reverse it) connected to the in input via the scale parameter. Setting the scale to 0 will pause the animation.

Transition

Very simple state machine (when you don't want to cope with a StateMachine node). Animations can be connected to the outputs and transition times can be specified. After setting the request and changing the animation playback, the transition node automatically clears the request on the next process frame by setting its transition_request value to an empty string ("").

# 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"]

BlendSpacе2D

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

../../_images/animtree7.gif

The ranges in X and Y can be controlled (and labeled for convenience). By default, points can be placed anywhere (right-click on the coordinate system or use the add point button) and triangles will be generated automatically using Delaunay.

../../_images/animtree8.gif

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

../../_images/animtree9.png

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

../../_images/animtree10.png

BlendSpacе1D

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

StateMachinе (машина состояний)

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).

For better blending

In Godot 4.0+, in order for the blending results to be deterministic (reproducible and always consistent), the blended property values must have a specific initial value. For example, in the case of two animations to be blended, if one animation has a property track and the other does not, the blended animation is calculated as if the latter animation had a property track with the initial value.

When using Position/Rotation/Scale 3D tracks for Skeleton3D bones, the initial value is Bone Rest. For other properties, the initial value is 0 and if the track is present in the RESET animation, the value of its first keyframe is used instead.

For example, the following AnimationPlayer has two animations, but one of them lacks a Property track for Position.

../../_images/blending1.webp

This means that the animation lacking that will treat those Positions as Vector2(0, 0).

../../_images/blending2.webp

This problem can be solved by adding a Property track for Position as an initial value to the RESET animation.

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

Примечание

Be aware that the RESET animation exists to define the default pose when loading an object originally. It is assumed to have only one frame and is not expected to be played back using the timeline.

Also keep in mind that the Rotation 3D tracks and the Property tracks for 2D rotation with Interpolation Type set to Linear Angle or Cubic Angle will prevent rotation of more than 180 degrees from the initial value as blended animation.

This can be useful for Skeleton3Ds to prevent the bones penetrating the body when blending animations. Therefore, Skeleton3D's Bone Rest values should be as close to the midpoint of the movable range as possible. This means that for humanoid models, it is preferable to import them in a T-pose.

../../_images/blending5.webp

You can see that the shortest rotation path from Bone Rests is prioritized rather than the shortest rotation path between animations.

If you need to rotate Skeleton3D itself more than 180 degrees by blend animations for movement, you can use Root Motion.

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()

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

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

../../_images/animtree15.gif

Контроль из кода

После построения дерева и его предварительного просмотра остается только один вопрос: "Как все это управляется из кода?".

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

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

../../_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

Путешествие конечного автомата

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. If there is no path of transitions starting at the current state and finishing at the destination state, the graph teleports to the destination state.

Чтобы использовать способность путешествия, необходимо сначала получить объект AnimationNodeStateMachinePlayback из узла AnimationTree (он экспортируется как свойство).

var state_machine = animation_tree["parameters/playback"]

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

state_machine.travel("SomeState")

Государственная машина должна быть запущена, прежде чем вы сможете отправиться в путешествие. Обязательно вызовите start() или выберите узел для Autoplay on Load.

../../_images/animtree18.png