Usando AnimationTree

Introducción

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.

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 usarse para hacer que un comando de búsqueda suceda a cualquier sub-hijo del gráfico de animación. Utilice este tipo de nodo para reproducir una Animación desde el inicio o una determinada posición de reproducción dentro del AnimationNodeBlendTree.

Después de configurar el tiempo y cambiar la reproducción de la animación, el nodo de búsqueda entra automáticamente en modo de suspensión en el siguiente cuadro de proceso estableciendo su valor de seek_position en -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

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 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
  • Inmediato: Cambiará al siguiente estado inmediatamente. El estado actual terminará y se mezclará con el principio del nuevo.

  • Sync: Cambiará al siguiente estado inmediatamente, pero buscará el nuevo estado a la posición de reproducción del viejo estado.

  • Al final: Esperará a que termine la reproducción del estado actual, y luego pasará al principio de la animación del siguiente estado.

Las transiciones también tienen algunas propiedades. Haga clic en cualquier transición y se mostrará en el muelle de inspección:

../../_images/animtree13.png
  • Switch Mode es el tipo de transición (ver arriba), puede ser modificado después de la creación aquí.

  • Auto Avance encenderá la transición automáticamente cuando se alcance este estado. Esto funciona mejor con el modo de interruptor Al final.

  • Condición de avance activará el avance automático cuando se establezca esta condición. Este es un campo de texto personalizado que puede ser llenado con un nombre de variable. La variable puede ser modificada desde el código (más sobre esto más adelante).

  • Xfade Time es el tiempo para cruzar entre este estado y el siguiente.

  • 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

Cuando se trabaja con animaciones 3D, una técnica popular es que los animadores usen el hueso del esqueleto de la raíz para dar movimiento al resto del esqueleto. Esto permite animar los personajes de manera que los pasos coincidan con el piso de abajo. También permite una interacción precisa con los objetos durante la cinematografía.

Al reproducir la animación en Godot, es posible seleccionar este hueso como la pista de movimiento de raíz. Al hacerlo, se cancelará la transformación del hueso visualmente (la animación se mantendrá en su lugar).

../../_images/animtree14.png

Después, el movimiento real puede ser recuperado a través de la API AnimationTree como una transformación:

anim_tree.get_root_motion_transform()

Esto puede ser alimentado a funciones como KinematicBody.move_and_slide para controlar el movimiento del personaje.

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

Controlando desde código

Después de construir el árbol y previsualizarlo, la única pregunta que queda es "¿Cómo se controla todo esto desde el código?".

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.

Los datos de la animación real están contenidos en el nodo AnimationTree y se accede a ellos a través de las propiedades. Revisa la sección "Parameters" del nodo AnimationTree para ver todos los parámetros que pueden ser modificados en tiempo real:

../../_images/animtree16.png

Esto es útil porque permite animarlos desde un AnimationPlayer, o incluso desde el mismo AnimationTree, permitiendo la realización de una lógica de animación muy compleja.

Para modificar estos valores del código, se debe obtener el camino de la propiedad. Esto se hace fácilmente pasando el ratón por encima de cualquiera de los parámetros:

../../_images/animtree17.png

Lo que permite establecerlos o leerlos:

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

Viaje de la máquina de estados

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.

Para usar la habilidad de viajar, primero debes recuperar el objeto AnimationNodeStateMachinePlayback del nodo AnimationTree (se exporta como una propiedad).

var state_machine = anim_tree["parameters/playback"]

Una vez recuperado, se puede utilizar llamando a una de las muchas funciones que ofrece:

state_machine.travel("SomeState")

La máquina de estado debe estar funcionando antes de que pueda viajar. Asegúrese de llamar a start() o elegir un nodo para Autoreproducir al cargar.

../../_images/animtree18.png