Voltar para o Blog
Quest Log

Root Motion na Unity: Quando Usar e Quando Desligar

Personagem 3D dando um passo largo com pegadas brilhantes no chão e uma seta mostrando o deslocamento vindo da animação

Unity root motion ou In Place? Entenda Apply Root Motion, OnAnimatorMove com CharacterController e Rigidbody, e corrija o personagem que volta ao lugar.

Ferramenta:Unity

Root Motion na Unity: Quando Usar e Quando Desligar

Root motion na Unity é quando a própria animação move o personagem: o deslocamento gravado no clip (o passo de uma caminhada, o avanço de um golpe) é aplicado no GameObject pelo Animator. A alternativa é a animação In Place, em que o corpo anima no lugar e o seu script decide para onde e com que velocidade o personagem anda. Nenhum dos dois é melhor em geral: a escolha depende do tipo de jogo e de quanto controle você quer dar ao jogador.

Aqui você vai entender a diferença na prática, ligar o Apply Root Motion, controlar o movimento com OnAnimatorMove usando CharacterController e Rigidbody, saber quando não usar root motion e corrigir os dois bugs clássicos: o personagem que volta ao ponto inicial e o que escorrega.

O que é Root Motion na Unity

Num clip Humanoid, a Unity calcula duas referências a cada frame:

  • Body Transform: o centro de massa do personagem, a referência mais estável do corpo.
  • Root Transform: a projeção do Body Transform no plano Y, calculada em tempo de execução.

A cada frame, a variação do Root Transform vira um delta de posição e rotação. Com Apply Root Motion ligado, esse delta é somado ao GameObject. Em rigs Generic, a referência é o osso escolhido em Root Node na aba Rig.

Na prática: um clip de corrida do Mixamo sem "In Place" desloca o corpo para a frente a cada ciclo. Com root motion, o GameObject anda exatamente essa distância. A velocidade do personagem passa a ser a velocidade em que o animador animou a corrida.

Root Motion vs In Place: diferença prática

Root MotionIn Place + script
Quem moveO clipO seu código
Pé deslizandoPraticamente nuncaAcontece se a velocidade não bate com a animação
Resposta ao inputSegue a aceleração da animaçãoImediata, você controla
Golpe com avançoDistância exata do clipVocê programa o avanço
Ajuste de velocidadeMexer no clip ou no multiplicadorMudar um número
MultiplayerMais difícil de prever no servidorSimples de sincronizar

Jogos de ação em terceira pessoa com personagem pesado, combate com deslocamento e animações de interação (subir em borda, abrir porta) tiram muito proveito de root motion. Plataforma, shooter rápido, top-down e qualquer jogo em que o controle precisa ser preciso ao pixel ficam melhores com In Place.

Existe um meio termo que muitos jogos usam: locomoção In Place pelo script, e root motion só em ataques, esquivas e animações especiais.

Apply Root Motion no Animator

O ajuste é uma caixa no componente Animator: Apply Root Motion. Antes de ligar, confira as importações dos clips na aba Animation do FBX:

  • Root Transform Rotation > Bake Into Pose: ligado, a rotação fica no corpo e o GameObject não gira. Use em clips retos (andar e correr para a frente) para o personagem não ir virando aos poucos.
  • Root Transform Position (Y) > Bake Into Pose: ligado, a altura fica no corpo. Use em quase tudo, menos em pulos e quedas em que o objeto precisa subir.
  • Root Transform Position (XZ) > Bake Into Pose: ligado, o deslocamento horizontal fica no corpo e não vai para o GameObject. Use em idles, para matar a deriva de pequenos deltas acumulados.

Ou seja: Bake Into Pose é o interruptor por clip e por eixo. Ligar o Apply Root Motion no Animator e fazer o bake de XZ num clip específico significa que só aquele clip não desloca o personagem.

Controlando o movimento com OnAnimatorMove

Se um script no mesmo GameObject do Animator implementar o método OnAnimatorMove, a Unity para de aplicar o root motion sozinha e entrega a responsabilidade para você. O Inspector do Animator mostra o campo Apply Root Motion como "Handled by Script". O método roda todo frame, depois que as máquinas de estado e as animações foram avaliadas, e você lê o deslocamento em animator.deltaPosition e animator.deltaRotation.

Isso é útil para três coisas: aplicar o movimento por um CharacterController ou Rigidbody (para respeitar colisão), multiplicar ou filtrar o deslocamento, e decidir por estado se o root motion vale ou não.

Root Motion com CharacterController e Rigidbody

Aplicar o delta direto no transform atravessa paredes. Passe pelo componente de física.

Com CharacterController, arquivo RootMotionController.cs:

using UnityEngine;

[RequireComponent(typeof(Animator), typeof(CharacterController))]
public class RootMotionController : MonoBehaviour
{
    [SerializeField] private float gravity = -20f;
    [SerializeField] private float rootMotionMultiplier = 1f;

    private Animator animator;
    private CharacterController controller;
    private float verticalVelocity;

    private void Awake()
    {
        animator = GetComponent<Animator>();
        controller = GetComponent<CharacterController>();
    }

    private void OnAnimatorMove()
    {
        if (controller.isGrounded && verticalVelocity < 0f)
        {
            verticalVelocity = -2f;
        }
        verticalVelocity += gravity * Time.deltaTime;

        Vector3 delta = animator.deltaPosition * rootMotionMultiplier;
        delta.y = verticalVelocity * Time.deltaTime;

        controller.Move(delta);
        transform.rotation *= animator.deltaRotation;
    }
}

O deslocamento horizontal vem do clip, e a gravidade vem do script. O input não move ninguém aqui: ele só alimenta os parâmetros do Animator (como Speed numa Blend Tree), e a animação escolhida desloca o corpo.

Com Rigidbody, mude o Update Mode do Animator para Fixed, para a animação rodar no mesmo passo da física. Arquivo RootMotionRigidbody.cs:

using UnityEngine;

[RequireComponent(typeof(Animator), typeof(Rigidbody))]
public class RootMotionRigidbody : MonoBehaviour
{
    private Animator animator;
    private Rigidbody rb;

    private void Awake()
    {
        animator = GetComponent<Animator>();
        rb = GetComponent<Rigidbody>();
    }

    private void OnAnimatorMove()
    {
        if (Time.deltaTime <= 0f) return;

        Vector3 velocity = animator.deltaPosition / Time.deltaTime;
        velocity.y = rb.linearVelocity.y; // preserva a gravidade
        rb.linearVelocity = velocity;
        rb.MoveRotation(rb.rotation * animator.deltaRotation);
    }
}

Converter o delta em velocidade, em vez de usar MovePosition, deixa a física resolver colisões e rampas. Repare no linearVelocity: é o nome atual no Unity 6, e o exemplo antigo com rb.velocity que circula por aí gera aviso de API obsoleta. Trave as rotações X e Z em Constraints para o personagem não tombar.

Root motion só em ataques e esquivas

Para o meio termo (locomoção por script, golpes por animação), marque os estados de ataque e esquiva com a Tag RootMotion no Inspector do estado e filtre dentro do OnAnimatorMove:

private static readonly int RootMotionTag = Animator.StringToHash("RootMotion");

private bool CurrentStateUsesRootMotion()
{
    AnimatorStateInfo state = animator.GetCurrentAnimatorStateInfo(0);
    return state.tagHash == RootMotionTag;
}

No OnAnimatorMove, aplique animator.deltaPosition só quando esse método devolver true. Nos outros estados, o script de locomoção move o controller normalmente. Um único dono do movimento por frame evita os dois sistemas somando deslocamento e o personagem andando o dobro.

Escolher entre root motion e script, integrar com física, câmera e combate, e fazer tudo isso parecer bom no controle é o tipo de decisão que trava projeto solo por semanas. No curso de Unity você constrói um jogo completo tomando essas decisões na ordem certa, com o porquê de cada uma, em vez de colar soluções de tutoriais diferentes que não conversam.

Curso de Unity
Quer fazer seu primeiro jogo na Unity?

No curso de Unity 6 da CursoGame.Dev você vai do zero ao primeiro jogo, com um desafio prático em cada level e suporte individual no WhatsApp quando travar.

Conhecer o curso de Unity
Suporte no WhatsAppAcesso vitalícioGarantia de 7 dias

Quando NÃO usar Root Motion

  • Plataforma 2D ou 3D com pulo preciso. O jogador precisa saber exatamente onde vai cair. Aceleração de animação atrapalha.
  • Shooter rápido e jogos competitivos. Resposta imediata vale mais que pé perfeito.
  • Multiplayer com previsão no cliente. Root motion depende do estado do Animator, que é mais difícil de reproduzir igual no servidor e no cliente.
  • Personagem com velocidade que muda por gameplay (buff de velocidade, lama, gelo). Com root motion, mudar a velocidade exige multiplicar o delta e, para o pé não deslizar, acelerar a animação junto.
  • Pixel art e sprite sheet. Não existe root motion útil em sprite, e o movimento por script é o padrão.

Nesses casos, baixe as animações In Place, deixe Apply Root Motion desligado e controle a Blend Tree pela velocidade real. O guia de game feel explica por que resposta imediata pesa tanto na sensação do controle.

Erros comuns: personagem voltando ao ponto inicial e escorregando

Anda e volta para o lugar. O clip tem deslocamento e Apply Root Motion está desligado: o corpo avança dentro do clip e, quando o ciclo reinicia, volta à origem. Ligue o Apply Root Motion ou troque pela versão In Place. Se o personagem anda certo e só "puxa" de volta no fim de um ataque, o clip de ataque precisa de Bake Into Pose em XZ desligado e o Animator com root motion.

Escorrega parado no idle. Pequenos deltas acumulados. Ligue Root Transform Position (XZ) > Bake Into Pose no idle.

Gira sozinho ao andar reto. Rotação residual do mocap. Root Transform Rotation > Bake Into Pose no clip, com Based Upon em Body Orientation.

Afunda ou flutua. Root Transform Position (Y) com Based Upon errado. Use Feet e ligue o bake. Se o problema é só com CharacterController, confira Center e Height do controller.

Atravessa parede. O root motion está indo direto para o transform. Implemente OnAnimatorMove passando pelo CharacterController ou pelo Rigidbody.

Golpe empurra o personagem para fora da plataforma. O clip de ataque tem avanço grande. Reduza com o multiplicador em OnAnimatorMove durante o ataque ou faça um raycast à frente e zere o delta se não houver chão. O avanço de golpe é parte do peso do ataque no sistema de combate corpo a corpo, então prefira limitar a remover.

Próximo passo

Faça o teste lado a lado: duplique o personagem, deixe um com root motion e o outro In Place com script, e jogue com os dois na mesma cena. Em poucos minutos fica claro qual combina com o seu jogo. Se você ainda está configurando os clips, volte ao guia de Mixamo na Unity para baixar as duas versões e acertar o Avatar.

Perguntas frequentes

O que é Apply Root Motion na Unity?

É a opção do componente Animator que pega o deslocamento e a rotação gravados na animação e aplica no GameObject. Ligada, quem move o personagem é o clip. Desligada, o personagem anima no lugar e o seu script é responsável pelo movimento.

Root motion ou In Place: qual é melhor?

Depende do jogo. Root motion dá pés que não deslizam e golpes com deslocamento preciso, bom para ação em terceira pessoa com peso. In Place com movimento por script dá controle imediato e previsível, bom para plataforma, shooter rápido e multiplayer.

Por que meu personagem anda e volta para o lugar?

O clip tem deslocamento, mas o Apply Root Motion está desligado, então o corpo anda dentro do clip e o GameObject fica parado. No fim do ciclo o corpo volta à origem. Ligue o Apply Root Motion ou baixe a versão In Place da animação.

Dá para usar root motion só em algumas animações?

Dá. Implemente OnAnimatorMove e aplique o deltaPosition só quando o estado atual pede, por exemplo durante ataques e esquivas, deixando a locomoção por script. Também dá para fazer o bake da posição nos clips que não devem mover o personagem.