Animator na Unity: Animator Controller do Zero
O Unity Animator é o sistema que decide qual animação o personagem toca a cada momento. Você cria um Animator Controller (um asset com uma máquina de estados), coloca nele os clips Idle, Walk e Jump, liga os estados com transições que dependem de parâmetros e, no código, só atualiza esses parâmetros: velocidade, se está no chão, velocidade vertical. O Animator faz o resto.
Este guia monta um Controller de personagem do zero no Unity 6.3 LTS, explica cada peça (estados, Entry, Any State, transições, parâmetros, layers) e entrega o script mínimo em C# que dirige tudo. Os exemplos usam um personagem 2D, mas o Controller funciona igual em 3D.
Animation Clip, Animator e Animator Controller: quem é quem
Três nomes parecidos, três coisas diferentes:
- Animation Clip (
.anim): uma animação. "Andar", "pular", "parado". Guarda keyframes: troca de sprite em 2D, rotação de ossos em 3D, ou qualquer propriedade (cor, posição, escala). - Animator Controller (
.controller): a máquina de estados. Diz quais clips existem, como passar de um para outro e quais parâmetros decidem isso. - Animator (componente): fica no personagem. Aponta para um Controller e toca os clips nos objetos daquele personagem. Em 3D humanoide, também aponta para um Avatar.
Separar o "o quê" (clips) do "quando" (Controller) do "em quem" (componente) é o que permite reaproveitar: o mesmo Controller pode animar dez inimigos, e o Animator Override Controller troca os clips mantendo a mesma lógica. É a mesma ideia de separar responsabilidades que aparece em padrões de projeto para jogos.
Se você vem de animação e quer entender como esse trabalho se divide num estúdio, o post sobre o que faz um animador de jogos mostra onde o Animator Controller entra no pipeline.
Criando o primeiro Animator Controller
Pré-requisito: três clips prontos (Idle, Walk, Jump). Em 2D, um jeito rápido de criar é selecionar os frames de um sprite fatiado e arrastar para a cena: a Unity cria o clip e um Controller automaticamente. Aqui vamos criar o Controller à mão para entender cada parte.
- No Project, clique com o botão direito e escolha Create > Animation > Animator Controller. Chame de
Player.controller. - No personagem, Add Component > Animator (se ainda não tiver) e arraste o
Player.controllerpara o campo Controller. - Abra Window > Animation > Animator. Com o personagem selecionado, a janela mostra o grafo do Controller.
- Arraste os três clips do Project para o grafo. Cada clip vira um estado (uma caixa).
O primeiro estado criado fica laranja: é o estado padrão, o que toca quando o jogo começa. Ele deve ser o Idle. Se não for, clique com o botão direito no Idle e escolha Set as Layer Default State.
Estados, Entry, Any State e transições
No grafo aparecem caixas especiais:
- Entry: de onde o Controller parte. A seta laranja dele aponta para o estado padrão.
- Any State: um atalho para "de qualquer estado". Uma transição saindo dele pode interromper qualquer animação. Útil para ações que valem sempre, como levar dano ou morrer.
- Exit: sai de uma sub-máquina de estados. Num Controller simples, você não usa.
Uma transição é a seta de um estado para outro. Crie clicando com o botão direito no estado de origem, Make Transition, e clicando no destino.
Ao selecionar uma transição, o Inspector mostra:
- Has Exit Time: se marcado, a transição espera o clip chegar num ponto (Exit Time) antes de acontecer. Para trocas que dependem do jogador (parado para andar, andar para pular), desmarque. Com ele marcado, o personagem continua andando no lugar até o clip chegar no Exit Time, mesmo depois que você soltou o botão.
- Transition Duration: tempo de mistura entre os dois clips. Em 3D, 0.1 a 0.25 dá suavidade. Em 2D com troca de sprite, use 0: não existe meio-termo entre dois frames de pixel art.
- Conditions: a lista de condições com parâmetros. Sem condição e sem Exit Time, a transição não tem como disparar (o Inspector avisa).
Transições a criar:
| De | Para | Condição |
|---|---|---|
| Idle | Walk | Speed Greater 0.1 |
| Walk | Idle | Speed Less 0.1 |
| Idle | Jump | IsGrounded false |
| Walk | Jump | IsGrounded false |
| Jump | Idle | IsGrounded true |
Uma alternativa é fazer Any State > Jump com IsGrounded false. Se fizer, desmarque Can Transition To Self nessa transição, senão o Jump reinicia a cada frame enquanto o personagem está no ar e a animação trava no primeiro quadro.
Parâmetros e o script que conversa com o Animator
Na janela Animator, aba Parameters, clique em + e crie:
Speed(Float): velocidade horizontal absoluta.IsGrounded(Bool): está no chão.VerticalSpeed(Float): sobe ou cai. Serve para trocar entre clip de subida e de queda, se você tiver os dois.
Existem quatro tipos de parâmetro (Float, Int, Bool, Trigger). Trigger é para eventos pontuais, como atacar; para um Controller de locomoção, Float e Bool bastam e evitam o problema de trigger guardado que dispara depois.
O script não decide animação. Ele só informa o estado do personagem ao Animator. Arquivo PlayerAnimator.cs, no personagem:
using UnityEngine;
[RequireComponent(typeof(Animator))]
public class PlayerAnimator : MonoBehaviour
{
private static readonly int SpeedId = Animator.StringToHash("Speed");
private static readonly int IsGroundedId = Animator.StringToHash("IsGrounded");
private static readonly int VerticalSpeedId = Animator.StringToHash("VerticalSpeed");
[SerializeField] private Rigidbody2D rb;
[SerializeField] private SpriteRenderer spriteRenderer;
[SerializeField] private Transform groundCheck;
[SerializeField] private float groundCheckRadius = 0.1f;
[SerializeField] private LayerMask groundLayer;
private Animator animator;
private void Awake()
{
animator = GetComponent<Animator>();
}
private void Update()
{
Vector2 velocity = rb.linearVelocity;
bool grounded = Physics2D.OverlapCircle(groundCheck.position, groundCheckRadius, groundLayer) != null;
animator.SetFloat(SpeedId, Mathf.Abs(velocity.x));
animator.SetBool(IsGroundedId, grounded);
animator.SetFloat(VerticalSpeedId, velocity.y);
if (Mathf.Abs(velocity.x) > 0.01f)
{
spriteRenderer.flipX = velocity.x < 0f;
}
}
private void OnDrawGizmosSelected()
{
if (groundCheck == null)
{
return;
}
Gizmos.color = Color.green;
Gizmos.DrawWireSphere(groundCheck.position, groundCheckRadius);
}
}
Pontos importantes:
Animator.StringToHashtransforma o nome em um id. A documentação recomenda usar o id para otimizar o acesso a parâmetros, e ele concentra os nomes no topo da classe. O nome precisa ser idêntico ao da aba Parameters, com maiúsculas.- O script lê o Rigidbody2D (
linearVelocity, nome atual no Unity 6) e um ground check comPhysics2D.OverlapCircle. Crie um filho vazioGroundChecknos pés do personagem e uma layerGroundpara o chão. - O movimento fica em outro script. Este só observa. Assim, trocar a física não quebra a animação e vice-versa.
Montar um Controller de três estados é tranquilo. A dificuldade aparece quando entram ataque, dano, morte, dash e interações, cada um com regras de quem interrompe quem, e o grafo vira uma teia. Organizar isso junto com código e física, num personagem que não trava, é exatamente o tipo de problema que um curso de Unity com projeto completo trabalha passo a passo.
Layers e Avatar Mask: animar só a parte de cima
Layers permitem tocar duas animações ao mesmo tempo em partes diferentes do corpo. O caso clássico: as pernas correm (layer Base) enquanto o tronco atira (layer UpperBody).
- Na aba Layers da janela Animator, clique em + e crie
UpperBody. - Crie uma Avatar Mask: Create > Animation > Avatar Mask. No Inspector dela, em Humanoid, desmarque pernas e raiz, deixe tronco, braços e cabeça. Para personagem não humanoide, use a seção Transform e marque só os ossos do tronco.
- Na engrenagem da layer
UpperBody, coloque a máscara em Mask, Weight em 1 e Blending em Override (substitui) ou Additive (soma ao que a Base já faz). - Dentro da layer, crie um estado vazio (sem clip) como padrão e um estado
Shoot. Com o estado vazio ativo, a layer não interfere.
Por código, animator.SetLayerWeight(layerIndex, peso) liga e desliga a layer de forma suave, por exemplo subindo o peso enquanto o jogador mira.
Em 2D com troca de sprite, layers servem menos, porque um sprite é uma imagem só. Elas voltam a ser úteis em personagens 2D montados por partes (com o pacote 2D Animation e ossos).
Erros comuns: animação que não toca e personagem travado na pose
A animação não toca. Na ordem: o Animator tem o Controller? O estado padrão é o certo? Abra a janela Animator com o jogo rodando e o personagem selecionado: o estado ativo mostra uma barra de progresso, e os parâmetros mostram os valores atuais. Se o parâmetro não muda, o problema é no script. Se muda e a transição não acontece, é a condição (Greater no lugar de Less é clássico).
A animação toca só uma vez. O clip está sem Loop Time. Selecione o .anim no Project e marque Loop Time no Idle e no Walk. No Jump, normalmente desmarcado.
Personagem travado na pose do primeiro frame. Transição de Any State com Can Transition To Self ligado, reiniciando o estado todo frame.
Animação atrasada ao apertar o botão. Has Exit Time ligado em transições de controle.
Personagem volta a uma pose estranha ou uma propriedade reseta. É o Write Defaults. Cada estado tem essa opção no Inspector; ligada, o estado escreve o valor padrão de propriedades que o Controller anima em outros estados e que ele não anima. Misturar estados com Write Defaults ligado e desligado no mesmo Controller dá resultados difíceis de prever. Escolha um padrão para o projeto inteiro (ligado em todos ou desligado em todos) e mantenha.
Warning "Parameter does not exist". Nome digitado diferente no script e na aba Parameters.
Próximo passo: Blend Tree
O Controller de três estados funciona, mas Walk e Run como estados separados geram troca seca. A Blend Tree mistura vários clips por um parâmetro: com Speed em 0 toca Idle, em 3 toca Walk, em 6 toca Run, e entre esses valores mistura suavemente. Em 2D, uma Blend Tree 2D escolhe a animação pela direção, útil em top-down com oito direções. O guia de Blend Tree na Unity monta as duas versões a partir do Controller que você acabou de criar.
Perguntas frequentes
Qual a diferença entre Animator e Animator Controller na Unity?
O Animator é o componente que fica no personagem e toca as animações. O Animator Controller é o asset com a máquina de estados: quais animações existem, como uma passa para outra e quais parâmetros decidem isso. Um mesmo Controller pode ser usado por vários personagens.
Por que minha animação não toca no Animator da Unity?
Confira se o componente Animator tem o Controller no campo Controller, se o estado padrão (laranja) é o que você espera, se a transição tem condição e se o parâmetro está mudando. Abra a janela Animator com o jogo rodando e selecione o personagem: o estado ativo fica com uma barra de progresso.
Preciso usar Animator.StringToHash?
Não é obrigatório, mas a documentação recomenda usar o id gerado para otimizar a leitura e escrita de parâmetros. Também concentra os nomes num lugar só, o que reduz erro de digitação. Guarde os ids em campos static readonly.
O que é Write Defaults no Animator?
É uma opção de cada estado. Ligada, o estado escreve o valor padrão de qualquer propriedade animada pelo Controller que ele mesmo não anima. Misturar estados com a opção ligada e desligada no mesmo Controller costuma causar propriedades que voltam ou travam sem motivo aparente. Escolha um padrão e mantenha.



