AnimationTree

Introducción

Con AnimationPlayer, Godot tiene uno de los sistemas de animación más flexibles que puedas encontrar en cualquier motor de juegos. La capacidad de animar prácticamente cualquier propiedad en cualquier nodo o recurso, además de tener pistas dedicadas de transformación, Bézier, llamada de funciones, audio y pistas de subanimación, es prácticamente única.

Sin embargo, el soporte para mezclar esas animaciones a través de AnimationPlayer es relativamente limitado, ya que sólo se puede establecer un tiempo fijo de transición de cruce.

AnimationTree es un nuevo nodo introducido en Godot 3.1 para gestionar transiciones avanzadas. Sustituye al antiguo AnimationTreePlayer, mientras que añade una gran cantidad de características y flexibilidad.

Creando un AnimationTree

Antes de empezar, debe quedar claro que un nodo AnimationTree no contiene sus propias animaciones. En su lugar, utiliza las animaciones contenidas en un nodo AnimationPlayer. De esta manera, puedes editar tus animaciones (o importarlas desde una escena 3D) como de costumbre y luego usar este nodo extra para controlar la reproducción.

La forma más común de usar "AnimationTree" es en una escena 3D. Al importar tus escenas de un formato de intercambio 3D, normalmente vendrán con animaciones integradas ( ya sean múltiples o separadas desde una más grande en la importación). Al final, la escena importada de Godot contendrá las animaciones en un nodo AnimationPlayer.

Como en raras ocasiones se utilizan las escenas importadas directamente en Godot (son instanciadas o heredadas), puedes colocar el nodo AnimationTree en tu nueva escena que contiene lo importado. Después, apunta el nodo AnimationTree al AnimationPlayer que fue creado en la escena importada.

Así es como se hace en Third Person Shooter demo, como referencia:

../../_images/animtree1.png

Se creó una nueva escena para el jugador con un KinematicBody como raíz. Dentro de esta escena, el archivo original .dae (Collada) fue instanciado y se creó un nodo AnimationTree.

Creando un árbol

Hay tres tipos principales de nodos que pueden ser usados en AnimationTree:

  1. Nodos Animation, que hacen referencia a una animación del AnimationTree vinculado.
  2. Nodos Animation Root, que se utilizan para combinar subnodos.
  3. Nodos Animation Blend, que se utilizan dentro de AnimationNodeBlendTree para combinar un solo gráfico a través de múltiples puertos de entrada.

Para establecer un nodo raíz en AnimationTree, hay algunos tipos disponibles:

../../_images/animtree2.png
  • AnimationNodeAnimation: Selecciona una animación de la lista y la reproduce. Este es el nodo raíz más simple, y generalmente no se usa directamente como raíz.
  • AnimationNodeBlendTree: Contiene muchos nodos de tipo blend, como mix, blend2, blend3, one shot, etc. Esta es una de las raíces más utilizadas.
  • AnimationNodeStateMachine: Contiene múltiples nodos raíz como hijos en un gráfico. Cada nodo se utiliza como un estado, y proporciona múltiples funciones para alternar entre los estados.
  • AnimationNodeBlendSpace2D: Permite colocar nodos raíz en un espacio de mezcla 2D. Controla la posición de mezcla en 2D para combinar varias animaciones.
  • AnimationNodeBlendSpace1D: Versión simplificada del anterior (1D).

Blend tree

Un AnimationNodeBlendTree puede contener nodos raíz y comunes usados para la mezcla. Los nodos se añaden al gráfico desde un menú:

../../_images/animtree3.png

Todos los blend trees contienen un nodo Output por defecto, y algo tiene que estar conectado a él para que las animaciones puedan reproducirse.

La forma más fácil de probar esta funcionalidad es conectar un nodo de Animation directamente:

../../_images/animtree4.png

Esto simplemente reproducirá la animación. Asegúrate de que el AnimationTree esté activo para que algo suceda en verdad.

A continuación se presenta una breve descripción de los nodos disponibles:

Blend2 / Blend3

Estos nodos se mezclarán entre dos o tres entradas mediante un valor de mezcla especificado por el usuario:

../../_images/animtree5.gif

Para mezclas más complejas, se aconseja usar espacios de mezcla en su lugar.

La mezcla también puede utilizar filtros, es decir, se puede controlar individualmente cuáles son las pistas que pasan por la función de mezcla. Esto es muy útil para superponer animaciones.

../../_images/animtree6.png

OneShot

Este nodo ejecutará una subanimación y volverá una vez que termine. Los tiempos de mezcla para el desvanecimiento de entrada y salida pueden ser personalizados, así como los filtros.

../../_images/animtree6b.gif

Seek

Este nodo puede ser usado para hacer que un comando de búsqueda le suceda a cualquier sub-hijo del gráfico. Después de establecer el tiempo, este valor vuelve a -1.

TimeScale

Permite escalar la velocidad de la animación (o invertirla) en cualquier nodo hijo. Poniéndolo en 0 se detendrá la animación.

Transition

Una máquina de estados muy simple (cuando no quieres lidiar con un nodo StateMachine). Las animaciones pueden ser conectadas a las salidas y se pueden especificar los tiempos de transición.

BlendSpace2D

BlendSpace2D es un nodo para hacer mezclas avanzadas en dos dimensiones. Se añaden puntos a un espacio bidimensional y luego se puede controlar una posición para determinar la mezcla:

../../_images/animtree7.gif

Los rangos en X e Y pueden ser controlados (y etiquetados para mayor comodidad). Por defecto, los puntos pueden ser colocados en cualquier lugar (sólo hay que hacer clic con el botón derecho del ratón en el sistema de coordenadas o usar el botón añadir punto) y los triángulos se generarán automáticamente usando Delaunay.

../../_images/animtree8.gif

También es posible dibujar los triángulos manualmente desactivando la opción triángulo automático, aunque esto rara vez es necesario:

../../_images/animtree9.png

Finalmente, es posible cambiar el modo de mezcla. Por defecto, la mezcla se realiza interpolando puntos dentro del triángulo más cercano. Cuando se trata de animaciones 2D (cuadro por cuadro), es posible que quieras cambiar al modo Discrete. Por otra parte, si quieres mantener la posición actual de reproducción al cambiar entre las animaciones discretas, hay un modo Carry. Este modo puede cambiarse en el menú Blend:

../../_images/animtree10.png

BlendSpace1D

Esto es similar a los espacios de mezcla 2D, pero en una dimensión (por lo que los triángulos no son necesarios).

StateMachine

This node is a relatively simple state machine. 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 ways.

../../_images/animtree11.gif

Existen varios tipos de transición:

../../_images/animtree12.png
  • Immediate: Will switch to the next state immediately. The current state will end and blend into the beginning of the new one.
  • Sync: Will switch to the next state immediately, but will seek the new state to the playback position of the old state.
  • At End: Will wait for the current state playback to end, then switch to the beginning of the next state animation.

Transitions also have a few properties. Click any transition and it will be displayed in the inspector dock:

../../_images/animtree13.png
  • Switch Mode is the transition type (see above), it can be modified after creation here.
  • Auto Advance will turn on the transition automatically when this state is reached. This works best with the At End switch mode.
  • Advance Condition will turn on auto advance when this condition is set. This is a custom text field that can be filled with a variable name. The variable can be modified from code (more on this later).
  • Xfade Time is the time to cross-fade between this state and the next.
  • Priority is used together with the travel() function from code (more on this later). When travelling from a state to another, give more priority to this node.
  • Disabled allows to disable this transition (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()
animTree.GetRootMotionTransform();

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 normally disabled during the game).

../../_images/animtree15.gif

Controlando desde código

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 the instances. Setting values in the nodes directly will affect all instances of the scene that uses this AnimationTree. This has some cool use cases, though, 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
animTree.Set("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.

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"]
AnimationNodeStateMachinePlayback stateMachine = (AnimationNodeStateMachinePlayback)animTree.Get("parameters/playback");

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

state_machine.travel("SomeState")
stateMachine.Travel("SomeState")