Usando AnimationTree¶
Introdução¶
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.
However, the support for blending those animations via AnimationPlayer
is relatively limited, as only a fixed cross-fade transition time can be set.
AnimationTree is a new node introduced in Godot 3.1 to deal with advanced transitions.
It supersedes the ancient AnimationTreePlayer
, while adding a huge amount of features and flexibility.
Criando uma AnimationTree¶
Antes de começar, é preciso deixar claro que um nó AnimationTree
não contém suas próprias animações. Em vez disso, ele usa animações contidas em um nó AnimationPlayer
. Dessa forma, você pode editar suas animações (ou importá-las de uma cena 3D) como de costume e, em seguida, usar esse nó extra para controlar a reprodução.
A maneira mais comum de usar o AnimationTree
é em uma cena 3D. Ao importar suas cenas de um formato de troca 3D, elas geralmente virão com animações incorporadas (várias ou divididas de uma grande na importação). No final, a cena Godot importada conterá as animações em um nó AnimationPlayer
.
Como você raramente usa cenas importadas diretamente no Godot (elas são instanciadas ou herdadas), é possível colocar o nó AnimationTree
em sua nova cena que contém a cena importada. Depois disso, aponte o nó AnimationTree
para o AnimationPlayer
que foi criado na cena importada.
É assim que isso é feito na demonstração do Jogo de Tiro em Terceira Pessoa , para referência:
Uma nova cena foi criada para o jogador com um KinematicBody
como raiz. Dentro dessa cena, o arquivo original .dae
(Collada) foi instanciado e um nó AnimationTree
foi criado.
Criando uma árvore¶
Há três tipos principais de nós que podem ser usados em AnimationTree
:
Nós de animação, que fazem referência a uma animação do link
AnimationTree
.Nós Animation Root, que são usados para misturar subnós.
Nós Animation Blend, que são usados em
AnimationNodeBlendTree
como combinação de gráfico único por meio de várias portas de entrada.
Para definir um nó raiz em AnimationTree
, há alguns tipos disponíveis:
AnimationNodeAnimation
: Seleciona uma animação da lista e a reproduz. Esse é o nó raiz mais simples e geralmente não é usado diretamente como raiz.AnimationNodeBlendTree
: Contém muitos nós do tipo blend, como mix, blend2, blend3, one shot, etc. Essa é uma das raízes mais usadas normalmente.AnimationNodeStateMachine
: Contém vários nós-raiz como filhos em um gráfico. Cada nó é usado como um estado , e fornece várias funções para alternar entre estados.AnimationNodeBlendSpace2D
: Permite colocar nós raiz em um espaço de mesclagem 2D. Controle a posição da mescla em 2D para misturar várias animações.AnimationNodeBlendSpace1D
: Versão simplificada do acima (1D).
Árvore (Tree) de mistura¶
Um AnimationNodeBlendTree
pode conter nós raiz e regulares usados para combinação. Os nós são adicionados ao gráfico a partir de um menu:
Todas as árvores de mesclagem contêm um nó Output
por padrão, e algo deve ser conectado a ele para que as animações sejam reproduzidas.
A maneira mais fácil de testar essa funcionalidade é conectar um nó Animation
diretamente a ele:
Isso simplesmente reproduzirá a animação. Certifique-se de que o AnimationTree
esteja ativo para que algo realmente aconteça.
A seguir, uma breve descrição dos nós disponíveis:
Blend2 / Blend3¶
Esses nós combinam duas ou três entradas com um valor de combinação especificado pelo usuário:
Para mesclagens mais complexas, é recomendável usar espaços de mesclagem.
A mesclagem também pode usar filtros, ou seja, você pode controlar individualmente quais faixas passam pela função de mesclagem. Isso é muito útil para colocar animações em camadas umas sobre as outras.
OneShot¶
Esse nó executará uma subanimação e retornará assim que for concluído. É possível personalizar os tempos de mesclagem para o fading in e o fading out, bem como os filtros.
Procurar¶
Esse nó pode ser usado para fazer com que um comando de busca ocorra em qualquer subfilho do gráfico de animação. Use esse tipo de nó para reproduzir um Animation
desde o início ou em uma determinada posição de reprodução dentro do AnimationNodeBlendTree
.
Após definir o tempo e alterar a reprodução da animação, o nó de busca entra automaticamente no modo de suspensão no próximo quadro do processo, definindo seu valor seek_position
para -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
// Play child animation from the start.
animTree.Set("parameters/Seek/seek_position", 0.0);
// Play child animation from 12 second timestamp.
animTree.Set("parameters/Seek/seek_position", 12.0);
TimeScale¶
Permite escalar a velocidade da animação (ou invertê-la) em quaisquer nós filhos. Defini-lo como 0 pausará a animação.
Transição¶
Uma máquina de estados muito simples (quando você não quiser lidar com um nó StateMachine
). As animações podem ser conectadas às saídas e os tempos de transição podem ser especificados.
BlendSpace2D¶
BlendSpace2D
é um nó para realizar a combinação avançada em duas dimensões. Os pontos são adicionados a um espaço bidimensional e, em seguida, uma posição pode ser controlada para determinar a mesclagem:
Os intervalos em X e Y podem ser controlados (e rotulados por conveniência). Por padrão, os pontos podem ser colocados em qualquer lugar (basta clicar com o botão direito do mouse no sistema de coordenadas ou usar o botão adicionar ponto ) e os triângulos serão gerados automaticamente usando Delaunay.
Também é possível desenhar os triângulos manualmente, desativando a opção auto triangle, embora isso raramente seja necessário:
Por fim, é possível alterar o modo de mesclagem. Por padrão, a mesclagem ocorre interpolando pontos dentro do triângulo mais próximo. Ao lidar com animações 2D (quadro a quadro), talvez você queira mudar para o modo Discrete. Como alternativa, se você quiser manter a posição de reprodução atual ao alternar entre animações discretas, há um modo Carry. Esse modo pode ser alterado no menu Blend:
BlendSpace1D¶
Isso é semelhante aos espaços de mesclagem 2D, mas em uma dimensão (portanto, triângulos não são necessários).
StateMachine(Máquina de Estados)¶
Esse nó atua como uma máquina de estado com nós raiz como estados. Os nós raiz podem ser criados e conectados através de linhas. Os estados são conectados através de Transitions, que são conexões com propriedades especiais. As transições são unidirecionais, mas duas podem ser usadas para se conectar em ambas as direções.
Existem muitos tipos de transições:
Imediato: Mudará para o próximo estado imediatamente. O estado atual terminará e se misturará ao início do novo.
Sync: Mudará para o próximo estado imediatamente, mas buscará o novo estado na posição de reprodução do estado antigo.
At End: Aguardará o término da reprodução do estado atual e, em seguida, alternará para o início da animação do próximo estado.
As transições também têm algumas propriedades. Clique em qualquer transição e ela será exibida no painel do inspetor:
Switch Mode é o tipo de transição (veja acima), ele pode ser modificado após a criação aqui.
O Auto Advance ativará a transição automaticamente quando esse estado for atingido. Isso funciona melhor com o modo de switch At End.
Advance Condition (Condição de avanço) ativará o avanço automático quando essa condição for definida. Esse é um campo de texto personalizado que pode ser preenchido com um nome de variável. A variável pode ser modificada a partir do código (mais sobre isso adiante).
Xfade Time é o tempo para cruzar entre este estado e o próximo.
Priority(Prioridade) é usada em conjunto com a função
travel()
do código (mais sobre isso posteriormente). As transições de prioridade mais baixa têm preferência ao percorrer a árvore.Disabled(Desativado) alterna a desativação desta transição (quando desativada, não será usada durante a mudança ou avanço automático).
Root motion(Movimento de raiz)¶
Ao trabalhar com animações em 3D, uma técnica popular é a de os animadores usarem o osso raiz do esqueleto para dar movimento ao restante do esqueleto. Isso permite animar os personagens de forma que os passos realmente correspondam ao piso abaixo. Também permite a interação precisa com objetos durante as cenas.
Ao reproduzir a animação no Godot, é possível selecionar esse osso como a faixa de movimento raiz . Ao fazer isso, a transformação do osso será cancelada visualmente (a animação permanecerá no lugar).
Depois disso, o movimento real pode ser recuperado por meio da API AnimationTree como uma transformação:
anim_tree.get_root_motion_transform()
animTree.GetRootMotionTransform();
Isso pode ser alimentado para funções como KinematicBody.move_and_slide para controlar o movimento do personagem.
Há também um nó de ferramenta, RootMotionView
, que pode ser colocado em uma cena e funcionará como um piso personalizado para seu personagem e suas animações (esse nó é desativado por padrão durante o jogo).
Controlando por código¶
Depois de criar a árvore e visualizá-la, a única pergunta que resta é "Como tudo isso é controlado por 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.
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:
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:
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.
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"]
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");
The state machine must be running before you can travel. Make sure to either call start()
or choose a node to Autoplay on Load.