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.
Checking the stable version of the documentation...
Usando 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 sub-animació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:

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.
Creando un árbol¶
Hay tres tipos principales de nodos que pueden ser usados en AnimationTree
:
Animation nodes, which reference an animation from the linked
AnimationPlayer
.Nodos Animation Root, que se utilizan para combinar subnodos.
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:

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).
Arbol de mezcla¶
Un AnimationNodeBlendTree
puede contener nodos raíz y comunes usados para la mezcla. Los nodos se añaden al gráfico desde un menú:

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:

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:

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.

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.

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"]
// Play child animation connected to "shot" port.
animationTree.Set("parameters/OneShot/request", (int)AnimationNodeOneShot.OneShotRequest.Fire);
// Abort child animation connected to "shot" port.
animationTree.Set("parameters/OneShot/request", (int)AnimationNodeOneShot.OneShotRequest.Abort);
// Get current state (read-only).
animationTree.Get("parameters/OneShot/active");
TimeSeek¶
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
.
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
// Play child animation from the start.
animationTree.Set("parameters/TimeSeek/seek_request", 0.0);
// Play child animation from 12 second timestamp.
animationTree.Set("parameters/TimeSeek/seek_request", 12.0);
TimeScale¶
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.
Transición¶
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"]
// Play child animation connected to "state_2" port.
animationTree.Set("parameters/Transition/transition_request", "state_2");
// Get current state name (read-only).
animationTree.Get("parameters/Transition/current_state");
// Get current state index (read-only).
animationTree.Get("parameters/Transition/current_index");
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:

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.

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

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:

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¶
Este nodo es una máquina de estado relativamente simple. Los nodos raíz pueden ser creados y conectados a través de líneas. Los estados se conectan a través de Transiciones, que son conexiones con propiedades especiales. Las transiciones son unidireccionales, pero dos se pueden usar para conectarlos en ambos sentidos.

Existen varios tipos de transición:

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:

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.
Prioridad se usa junto con la función
travel()
desde el código (más sobre esto más adelante). Cuando se viaja de un estado a otro, hay que dar más prioridad a este nodo.Desactivado permite desactivar esta transición (no se usará durante el viaje o el avance automático).
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.

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

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


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

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.
Movimiento raíz¶
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).

Después, el movimiento real puede ser recuperado a través de la API AnimationTree como una transformación:
# 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()
// Get the motion delta.
animationTree.GetRootMotionPosition();
animationTree.GetRootMotionRotation();
animationTree.GetRootMotionScale();
// Get the actual blended value of the animation.
animationTree.GetRootMotionPositionAccumulator();
animationTree.GetRootMotionRotationAccumulator();
animationTree.GetRootMotionScaleAccumulator();
This can be fed to functions such as CharacterBody3D.move_and_slide to control the character movement.
También hay un nodo de herramientas, RootMotionView
, que puede ser colocado en una escena y actuará como un piso personalizado para tu personaje y las animaciones (este nodo normalmente se desactiva durante el juego).

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?".
Tengan en cuenta que los nodos de animación son sólo recursos y, como tales, se comparten entre todas las instancias. Poner valores en los nodos afectará directamente a todas las instancias de la escena que usa este AnimationTree
. Sin embargo, esto tiene algunos casos de uso interesantes, por ejemplo, puedes copiar y pegar partes de tu árbol de animación, o reutilizar nodos con un diseño complejo (como una máquina de estados o un espacio de mezcla) en diferentes árboles de animación.
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:

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:

Lo que permite establecerlos o leerlos:
animation_tree.set("parameters/eye_blend/blend_amount", 1.0)
# Simpler alternative form:
animation_tree["parameters/eye_blend/blend_amount"] = 1.0
animationTree.Set("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.
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.
Para usar la habilidad de viajar, primero debes recuperar el objeto AnimationNodeStateMachinePlayback del nodo AnimationTree
(se exporta como una propiedad).
var state_machine = animation_tree["parameters/playback"]
AnimationNodeStateMachinePlayback stateMachine = (AnimationNodeStateMachinePlayback)animationTree.Get("parameters/playback");
Una vez recuperado, se puede utilizar llamando a una de las muchas funciones que ofrece:
state_machine.travel("SomeState")
stateMachine.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.
