Voltar para o Blog
Quest Log

Character Controller vs Rigidbody na Unity: Qual Usar

Dois personagens em cápsula lado a lado, um subindo degraus e outro empurrando uma caixa numa rampa

Unity Character Controller vs Rigidbody: o que cada um faz sozinho, o que você programa, rampas, degraus, caixas e um critério para o primeiro projeto 3D.

Ferramenta:UnityC#

Character Controller vs Rigidbody na Unity: Qual Usar

Na comparação Unity Character Controller vs Rigidbody, a resposta curta é: o Character Controller é um personagem pronto para andar em cenário (sobe degraus, respeita rampa, não atravessa parede) mas ignora a física; o Rigidbody participa da física de verdade (é empurrado, empurra, reage a explosões) mas você tem que programar tudo o que o Character Controller já resolve. Para o primeiro jogo 3D em terceira ou primeira pessoa, o Character Controller costuma ser o caminho mais curto.

Este post compara os dois ponto a ponto: o que cada um faz sozinho, o que fica por sua conta, como cada um lida com gravidade, rampas, degraus e caixas, e uma tabela de decisão por tipo de jogo. Código C# para Unity 6.3 LTS.

Unity Character Controller vs Rigidbody: resumo

Character ControllerRigidbody
Sobe degrausSim (Step Offset)Não, você programa
Limite de rampaSim (Slope Limit)Não, você programa
Não atravessa paredeSim, desliza nelaSim, pela física
GravidadeSó no SimpleMove; no Move, você somaAutomática
PuloVocê programalinearVelocity ou impulso
É empurrado por objetosNãoSim
Empurra objetosNão, você programaSim
Reage a explosãoNão, você programaAddExplosionForce
Plataforma móvelVocê programaVocê programa (com ajustes)
Previsibilidade do controleAltaDepende de configurar bem

O Character Controller troca realismo físico por controle previsível. O Rigidbody faz o contrário.

Como o Character Controller funciona

O Character Controller é um collider em forma de cápsula com um algoritmo de movimento próprio. Você chama Move com o deslocamento desejado, ele tenta mover a cápsula, e quando encontra obstáculo desliza ao longo dele, sobe o degrau se couber no Step Offset e para em rampas mais íngremes que o Slope Limit.

A página do Character Controller no manual do Unity 6.3 deixa duas coisas explícitas: o controller não reage a forças sozinho e não empurra Rigidbodies automaticamente. Ele se move só quando você chama Move ou SimpleMove.

Move vs SimpleMove. SimpleMove(velocidade) recebe velocidade em unidades por segundo, ignora o eixo Y e aplica gravidade automaticamente. Serve para NPC que só anda. Como ignora Y, não dá para pular com ele. Move(deslocamento) recebe o deslocamento do frame (já multiplicado por Time.deltaTime), não aplica gravidade e aceita qualquer direção. É o que você usa no jogador.

Arquivo JogadorCC.cs, personagem com movimento, gravidade e pulo usando as ações padrão do Input System:

using UnityEngine;
using UnityEngine.InputSystem;

[RequireComponent(typeof(CharacterController))]
public class JogadorCC : MonoBehaviour
{
    [SerializeField] private float velocidade = 5f;
    [SerializeField] private float alturaPulo = 1.2f;
    [SerializeField] private float gravidade = -20f;

    private CharacterController controller;
    private InputAction acaoMover;
    private InputAction acaoPular;
    private float velocidadeVertical;

    private void Awake()
    {
        controller = GetComponent<CharacterController>();
        acaoMover = InputSystem.actions.FindAction("Move");
        acaoPular = InputSystem.actions.FindAction("Jump");
    }

    private void Update()
    {
        Vector2 entrada = acaoMover.ReadValue<Vector2>();
        Vector3 horizontal = (transform.right * entrada.x + transform.forward * entrada.y) * velocidade;

        if (controller.isGrounded && velocidadeVertical < 0f)
        {
            velocidadeVertical = -2f; // mantém o controller colado no chão
        }

        if (controller.isGrounded && acaoPular.WasPressedThisFrame())
        {
            velocidadeVertical = Mathf.Sqrt(alturaPulo * -2f * gravidade);
        }

        velocidadeVertical += gravidade * Time.deltaTime;

        Vector3 deslocamento = (horizontal + Vector3.up * velocidadeVertical) * Time.deltaTime;
        controller.Move(deslocamento);
    }
}

Três detalhes:

  • Roda no Update, não no FixedUpdate. O Character Controller não faz parte da simulação de corpos, então o movimento acompanha o frame.
  • O -2f no chão. isGrounded só é verdadeiro se o último Move encostou no chão. Zerar a velocidade vertical faz o controller parar de encostar e o isGrounded pisca entre verdadeiro e falso. Uma pequena força para baixo mantém o contato.
  • A fórmula do pulo (Mathf.Sqrt(altura * -2 * gravidade)) dá a velocidade inicial exata para atingir alturaPulo metros. Você ajusta a altura em metros, não um número mágico.

O pulo completo com coyote time e pulo variável está no post de pulo com Character Controller 3D.

Como um Rigidbody controla personagem

Com Rigidbody, o personagem é um corpo físico como uma caixa. Você usa um CapsuleCollider, marca Freeze Rotation X e Z para ele não tombar, liga Interpolate para a câmera não tremer, e move atribuindo linearVelocity no FixedUpdate, preservando o Y para a gravidade continuar agindo.

O que você ganha de graça: gravidade, ser empurrado por objetos e explosões, empurrar caixas com a massa certa, interagir com joints e ragdoll sem troca de sistema.

O que fica por sua conta:

  • Degraus. A cápsula bate no degrau como numa parede. Você precisa de um raycast à frente dos pés e de um impulso para cima, ou de rampas invisíveis sobre as escadas.
  • Rampas. Subindo, o personagem perde velocidade; descendo, ele "pula" a cada passo porque a velocidade horizontal tira ele do chão. A correção é projetar o movimento no plano da rampa com Vector3.ProjectOnPlane(direcao, normalDoChao).
  • Grudar na parede. O atrito da cápsula segura o personagem contra a parede no ar. Precisa de um Physics Material com atrito zero.
  • Ground check. Rigidbody não tem isGrounded. Raycast ou SphereCast nos pés.

Nada disso é difícil isoladamente, mas é uma lista. O script de movimento por velocidade, com AddForce, linearVelocity e MovePosition lado a lado, segue o mesmo padrão do personagem com Rigidbody de qualquer jogo 3D: input no Update, física no FixedUpdate.

Escolher entre os dois é a primeira decisão do personagem. As seguintes vêm em cascata: animação que acompanha a velocidade, câmera que não atravessa parede, plataforma móvel, inimigos que empurram. Cada uma tem uma resposta diferente dependendo da base que você escolheu, e é nesse encaixe que muita gente refaz o personagem três vezes. O curso de Unity faz essa escolha dentro de um jogo completo e mostra as consequências dela em cada sistema seguinte.

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

Gravidade, rampas e degraus

Gravidade. No Character Controller com Move, você mantém velocidadeVertical e soma a gravidade, como no script acima. Vantagem: você escolhe a gravidade do personagem sem mexer na do projeto, e gravidades maiores que a real (-20, -30) são comuns para dar peso ao pulo. No Rigidbody, a gravidade vem de Project Settings > Physics, e para personalizar você desliga Use Gravity e aplica a sua com AddForce(..., ForceMode.Acceleration).

Rampas. O Character Controller sobe rampas até o Slope Limit em graus; acima disso, trata como parede. O manual recomenda não usar valores pequenos demais. Num Rigidbody, a física sobe qualquer rampa que o atrito permita, e o limite você programa comparando o ângulo da normal com Vector3.Angle(normal, Vector3.up).

Degraus. O Step Offset do Character Controller define a altura máxima que ele sobe sem pular. O manual sugere algo entre 0,1 e 0,4 para um humano de 2 metros, e alerta que o valor não pode ser maior que a altura do controller. Em Rigidbody, não existe equivalente pronto.

Skin Width. Exclusivo do Character Controller: uma margem em volta da cápsula que evita que ela fique presa em paredes. O manual recomenda cerca de 10% do Radius. Valor muito baixo faz o personagem travar em quinas; muito alto deixa ele flutuando visivelmente acima do chão.

Empurrar objetos e ser empurrado

Empurrar com Character Controller. Ele não empurra nada sozinho. O callback OnControllerColliderHit é chamado quando o Move encosta em algum collider, e é ali que você aplica o empurrão. Arquivo EmpurrarCaixas.cs, no mesmo objeto do JogadorCC:

using UnityEngine;

[RequireComponent(typeof(CharacterController))]
public class EmpurrarCaixas : MonoBehaviour
{
    [SerializeField] private float forcaEmpurrao = 2f;

    private void OnControllerColliderHit(ControllerColliderHit hit)
    {
        Rigidbody corpo = hit.collider.attachedRigidbody;

        if (corpo == null || corpo.isKinematic)
        {
            return;
        }

        // Não empurra para baixo o que está debaixo dos pés.
        if (hit.moveDirection.y < -0.3f)
        {
            return;
        }

        Vector3 direcao = new Vector3(hit.moveDirection.x, 0f, hit.moveDirection.z);
        corpo.linearVelocity = direcao * forcaEmpurrao;
    }
}

Atribuir a velocidade dá um empurrão firme e previsível, que ignora a massa. Se você quer caixas pesadas mais difíceis de empurrar, troque por corpo.AddForce(direcao * forcaEmpurrao / corpo.mass, ForceMode.VelocityChange) e ajuste.

Ser empurrado com Character Controller. Também não acontece. Um inimigo dinâmico batendo no jogador é barrado como se o jogador fosse uma parede. Knockback precisa de uma variável de "velocidade externa" somada ao deslocamento do Move e reduzida a cada frame.

Com Rigidbody, os dois lados vêm prontos: o jogador empurra caixas conforme as massas e é jogado longe pela explosão. O custo é o oposto: um inimigo pesado batendo no jogador pode empurrar o personagem para fora da plataforma sem você querer, e você passa a controlar massas e limites em vez de escrever o empurrão.

Tabela de decisão por tipo de jogo

Tipo de jogoEscolha comumPor quê
FPS, terceira pessoa de exploraçãoCharacter ControllerControle preciso, escadas e rampas sem esforço
Plataforma 3D com pulos exatosCharacter ControllerPulo e gravidade sob seu controle total
Jogo de física (empurrar, construir, ragdoll)RigidbodyA graça é a física reagir
Personagem que vira bola, nave ou veículoRigidbodyMovimento é física por natureza
NPC simples que só andaCharacter Controller com SimpleMove, ou NavMeshAgentSem pulo, gravidade pronta
Multijogador competitivoDepende da solução de redePrevisibilidade costuma pesar mais

Critério para o primeiro projeto: se você não sabe responder "a graça do meu jogo é a física reagindo?", comece com Character Controller. Você termina o movimento mais rápido, e as exceções (empurrar caixa, knockback) se resolvem com os callbacks acima.

Quando não usar cada um

Não use Character Controller se o personagem precisa ser jogado longe por explosões com frequência, interagir com joints (pendurar numa corda física), virar ragdoll e voltar várias vezes, ou se o jogo inteiro gira em torno de física emergente. Cada uma dessas coisas vira código manual.

Não use Rigidbody se você precisa de escadas sem rampas invisíveis, pulo com altura exata em qualquer situação e controle que nunca é afetado por um objeto que bateu de lado. Dá para chegar lá, mas a soma de ajustes costuma custar mais do que escrever empurrões manuais no Character Controller.

Não use os dois no mesmo objeto. Um Rigidbody dinâmico junto do Character Controller disputa a posição, e o resultado é tremedeira e teleporte.

Próximo passo

Crie dois personagens na mesma cena: um com JogadorCC + EmpurrarCaixas e outro com Rigidbody e movimento por velocidade. Monte uma escada, uma rampa de 40 graus, uma rampa de 60 graus e três caixas de massas diferentes. Passe com os dois por tudo e anote o que cada um faz sozinho e o que travou.

Se você também usa Godot, o comparativo de RigidBody2D vs CharacterBody2D no Godot faz a mesma escolha do lado de lá, e o guia de física de jogos no Godot explica os tipos de corpo com outros nomes. O dilema é o mesmo nas duas engines: controle previsível ou física de verdade.

Perguntas frequentes

Qual a diferença entre Move e SimpleMove no Character Controller?

SimpleMove recebe velocidade em unidades por segundo, ignora o eixo Y e aplica a gravidade sozinho, mas não permite pulo. Move recebe um deslocamento já multiplicado pelo tempo, não aplica gravidade e aceita qualquer direção, então é o que você usa quando o personagem pula.

O Character Controller tem gravidade?

Só no SimpleMove. Com Move, que é o método usado na maioria dos jogos, você mantém uma velocidade vertical no script, soma a gravidade a cada frame e inclui esse valor no vetor passado ao Move.

Character Controller empurra Rigidbody?

Não sozinho. O manual do Unity 6.3 diz que o controller não reage a forças e não empurra Rigidbodies automaticamente. Para empurrar caixas, use o callback OnControllerColliderHit e aplique velocidade ou força no Rigidbody atingido.

Posso usar Character Controller e Rigidbody juntos?

Não no mesmo objeto. O Character Controller já é um collider com sua própria lógica de movimento, e um Rigidbody dinâmico no mesmo objeto disputa o controle da posição. Escolha um dos dois para o corpo do personagem.