Voltar para o Blog
Quest Log

Fisica 2D no Godot: RigidBody2D vs CharacterBody2D (e quando usar cada corpo)

Comparativo visual entre RigidBody2D e CharacterBody2D na fisica 2D do Godot 4

Fisica 2D no Godot 4 sem confusao: entenda RigidBody2D vs CharacterBody2D, StaticBody2D e Area2D, com regra de decisao e exemplos tipados em GDScript.

Comecar na fisica 2D no Godot 4 costuma travar todo mundo no mesmo ponto: a engine tem quatro tipos de corpo (CharacterBody2D, RigidBody2D, StaticBody2D e Area2D) e nao fica obvio qual usar. Ai o iniciante escolhe no chute, e vem o classico "meu personagem nao colide", "ele atravessa a parede" ou "ele escorrega feito sabao". A boa noticia: a duvida de RigidBody2D vs CharacterBody2D tem uma regra de decisao simples, e depois que ela cai a ficha o resto encaixa. Neste post eu mato essa confusao com exemplos tipados e uma tabela de "qual usar quando".

Fisica 2D no Godot: os dois times de corpos

Antes de decorar nomes, entenda a divisao mais importante da fisica 2D no Godot. Existem dois jeitos de um objeto se mover no mundo:

  1. Controlado pela simulacao. A engine de fisica cuida de tudo: aplica gravidade, resolve colisoes, faz o objeto quicar, girar e empurrar outros. Voce so da o empurrao inicial (uma forca ou impulso) e observa. Esse e o mundo do RigidBody2D.
  2. Controlado por codigo. Voce, o programador, decide para onde o objeto vai a cada quadro. A engine ajuda a detectar e deslizar contra paredes, mas quem manda na velocidade e voce. Esse e o mundo do CharacterBody2D.

Sacar essa diferenca resolve 80% das duvidas. Quando alguem pergunta "RigidBody2D ou CharacterBody2D?", a pergunta real e: quem decide o movimento, a fisica ou o meu codigo? Se voce quer controle firme e responsivo (pulo com altura exata, aceleracao que voce afina), voce quer decidir no codigo. Se voce quer comportamento natural e caotico (uma caixa que tomba, um barril que rola escada abaixo), deixe a fisica decidir.

Os quatro tipos de corpo, um por um

CharacterBody2D: o corpo que voce dirige

O CharacterBody2D e o corpo de personagem por excelencia. Ele nao sofre gravidade sozinho, nao e empurrado por colisao e nao quica: ele so anda para onde voce mandar. A engine entra com uma ajuda enorme, o metodo move_and_slide(), que move o corpo pela velocity atual e desliza suavemente ao esbarrar em paredes e rampas, em vez de grudar ou tremer.

Use CharacterBody2D para: o jogador de um plataforma, um personagem top-down, um inimigo com IA de patrulha, qualquer coisa que precise de movimento previsivel e responsivo.

RigidBody2D: o corpo que a fisica dirige

O RigidBody2D e o oposto. Voce nao seta a posicao dele na mao (fazer isso briga com a simulacao e causa bugs). Em vez disso, voce aplica forcas e impulsos, e a engine calcula massa, gravidade, atrito e ricochete. Ele colide com tudo, empurra e e empurrado.

Use RigidBody2D para: caixas empilhaveis, barris que rolam, destrocos, uma bola que quica, projeteis que ricocheteiam na parede, pecas de fisica tipo Angry Birds.

StaticBody2D: o corpo que nao se move

O StaticBody2D e o mais simples e o mais barato. Ele e solido, colide com todo mundo, mas nao se move (ou se move so quando voce o move de proposito, tipo uma plataforma que voce anima). Serve de obstaculo.

Use StaticBody2D para: chao, paredes, teto, plataformas fixas, limites do mapa, qualquer geometria parada do cenario.

Area2D: o corpo que so observa

O Area2D nao e solido. Nada bate nele como parede, ele nao empurra ninguem. O que ele faz e detectar sobreposicao: avisar quando algo entra ou sai do seu espaco, atraves dos sinais body_entered, body_exited, area_entered e area_exited. E um sensor.

Use Area2D para: zona de dano (hitbox e hurtbox), coleta de moeda, checkpoint, gatilho de cutscene, sensor de "o jogador chegou aqui". Se voce quer detectar contato sem bloquear o movimento, e Area2D. Aprofundei esse padrao no guia de hitbox e hurtbox com Area2D no Godot, que mostra como montar dano confiavel sem transformar todo mundo em parede.

O CollisionShape2D: sem ele, nada colide

Aqui esta a causa numero um do "meu personagem nao colide". Nenhum desses corpos tem forma por conta propria. Um CharacterBody2D, RigidBody2D, StaticBody2D ou Area2D e so um node com regras de fisica; a forma que colide vem de um node filho CollisionShape2D (ou CollisionPolygon2D).

E nao basta adicionar o CollisionShape2D: voce precisa atribuir um recurso de shape a ele no Inspector (um RectangleShape2D, CircleShape2D, CapsuleShape2D, etc.). Um CollisionShape2D sem shape aparece como aviso amarelo na cena e nao colide com nada. Se seu corpo atravessa paredes, cheque nesta ordem: (1) existe um CollisionShape2D filho? (2) ele tem um shape atribuido? (3) as camadas de colisao (collision_layer e collision_mask) fazem os dois corpos se enxergarem?

Próximo nível
Quer aprender isso na prática?

No CursoGame.Dev você sai dos tutoriais soltos e constrói jogos publicáveis, com trilha progressiva, quests práticas e feedback real.

Conhecer a plataforma
+500 alunos4.9/5Garantia 7 dias

Regra de decisao: qual corpo usar quando

Guarde esta tabela. Ela responde a maioria das escolhas:

Voce quer que o objeto...Use
Se mova por codigo, com controle preciso (jogador, inimigo)CharacterBody2D
Obedeca a fisica: cai, quica, tomba, rola, empurraRigidBody2D
Fique parado e sirva de parede/chao solidoStaticBody2D
So detecte contato, sem bloquear nada (gatilho, dano)Area2D

Regra rapida em uma frase: personagem e CharacterBody2D, cenario parado e StaticBody2D, coisa que quica e RigidBody2D, sensor e Area2D.

Exemplo tipado: CharacterBody2D com gravidade e pulo

Aqui esta um controlador de plataforma completo e correto para Godot 4. Repare que velocity e propriedade do node e que move_and_slide() nao recebe argumento nenhum:

extends CharacterBody2D

const VELOCIDADE: float = 300.0
const FORCA_PULO: float = -450.0
const GRAVIDADE: float = 1200.0

func _physics_process(delta: float) -> void:
    # 1. Aplica gravidade enquanto estiver no ar.
    if not is_on_floor():
        velocity.y += GRAVIDADE * delta

    # 2. Pulo: so quando esta no chao.
    if Input.is_action_just_pressed("ui_accept") and is_on_floor():
        velocity.y = FORCA_PULO

    # 3. Movimento horizontal por input.
    var direcao: float = Input.get_axis("ui_left", "ui_right")
    if direcao != 0.0:
        velocity.x = direcao * VELOCIDADE
    else:
        # Zera a velocidade horizontal para NAO escorregar.
        velocity.x = move_toward(velocity.x, 0.0, VELOCIDADE)

    # 4. Move o corpo usando a velocity atual. Sem argumentos no Godot 4.
    move_and_slide()

Tres detalhes que consertam os bugs mais comuns:

  • Escorregar: o bloco else com move_toward(velocity.x, 0.0, VELOCIDADE) zera a velocidade horizontal quando nao ha input. Sem isso, o move_and_slide() mantem a ultima velocity e o personagem desliza para sempre.
  • is_on_floor(): so funciona depois que voce chamou move_and_slide() ao menos uma vez, porque e ele que atualiza o estado de contato. Por isso a checagem no proximo quadro ja e confiavel.
  • delta: multiplicar a gravidade por delta deixa a fisica independente do FPS. Como estamos em _physics_process, o delta e fixo e estavel.

Se voce quer ir mais fundo em pulo variavel, coyote time e aceleracao com sensacao boa, montei um passo a passo dedicado em movimento de personagem em plataforma 2D.

Exemplo tipado: RigidBody2D com forca e impulso

Agora o outro time. Com RigidBody2D voce nao mexe na position nem chama move_and_slide(). Voce empurra a fisica. Existem dois jeitos principais:

  • Impulso: um empurrao instantaneo, como um chute. Ideal para pulo, tiro, explosao.
  • Forca: uma pressao continua, aplicada quadro a quadro, como vento ou propulsao de nave.
extends RigidBody2D

const FORCA_IMPULSO: float = 400.0
const FORCA_CONTINUA: float = 800.0

func _ready() -> void:
    # Empurrao unico assim que nasce: sai voando para a direita e para cima.
    var impulso: Vector2 = Vector2(FORCA_IMPULSO, -FORCA_IMPULSO)
    apply_central_impulse(impulso)

func _physics_process(delta: float) -> void:
    # Forca continua enquanto segura a tecla (tipo propulsor).
    if Input.is_action_pressed("ui_up"):
        var empurrao: Vector2 = Vector2(0.0, -FORCA_CONTINUA)
        apply_central_force(empurrao)

Note as diferencas de mentalidade em relacao ao CharacterBody2D:

  • Nao existe velocity = seguido de move_and_slide(). Voce declara a intencao (forca/impulso) e a engine resolve o resto, incluindo gravidade, atrito e colisao.
  • apply_central_impulse() ignora rotacao e empurra pelo centro de massa; se voce usar apply_impulse() com um ponto deslocado, o corpo tambem gira. Isso e otimo para uma caixa tombar de forma natural.
  • Se voce sentir necessidade de forcar a posicao exata de um RigidBody2D todo quadro, e sinal de que voce queria um CharacterBody2D desde o comeco. Nao lute contra a simulacao.

Erros comuns que confundem iniciantes

  • Mover a position de um RigidBody2D na mao. Isso teleporta o corpo e quebra a simulacao (ele atravessa paredes e "explode" ao colidir). Use forca/impulso.
  • Esperar que Area2D bloqueie o jogador. Area2D so avisa, nunca para. Se voce quer uma porta solida, e StaticBody2D com colisao, e voce libera removendo a colisao.
  • Colocar movimento de fisica no _process em vez de _physics_process. A fisica roda em um passo fixo separado do render. Movimento de corpo vai em _physics_process(delta: float).
  • Esquecer o CollisionShape2D ou deixar sem shape. Repito porque e o campeao de tempo perdido: sem shape valido, nao ha colisao.
  • Camadas de colisao erradas. Dois corpos so colidem se a collision_layer de um estiver na collision_mask do outro. Se nada bate mesmo com shapes certos, olhe as camadas.

Onde isso te leva

A regra de decisao (personagem no CharacterBody2D, cenario no StaticBody2D, fisica solta no RigidBody2D, sensor no Area2D) resolve a duvida do dia a dia e ja te tira do lugar. Mas dominar fisica 2D de verdade e outro nivel: sincronizar hitbox com animacao, encadear estados de movimento, tratar rampas e plataformas moveis, combinar corpos controlados por codigo com corpos de simulacao na mesma cena sem que um quebre o outro. Isso e o tipo de coisa que voce constroi com projeto guiado e repeticao, nao lendo um post solto.

Se voce quer parar de tropecar em cada tipo de corpo e passar a montar mecanica com seguranca, e disso que trata o melhor curso de Godot: do primeiro CharacterBody2D ate sistemas de jogo completos, com quem ja passou por todos esses tropecos. Comece pela regra deste post hoje e leve o resto a serio depois.

Perguntas frequentes

Qual a diferenca entre RigidBody2D e CharacterBody2D?

O RigidBody2D e controlado pela simulacao de fisica: a engine calcula gravidade, colisao e ricochete sozinha. O CharacterBody2D e controlado por codigo: voce decide a velocity e chama move_and_slide(). Use CharacterBody2D quando quer controle preciso do movimento (personagem de plataforma, top-down) e RigidBody2D quando quer que a fisica mande (caixas, barris, projeteis que quicam).

Por que meu personagem no Godot nao colide ou atravessa a parede?

Quase sempre falta um CollisionShape2D com um shape atribuido no Inspector, ou o node esta na camada de colisao errada. Um corpo fisico sem CollisionShape2D valido nao tem forma para colidir. Confira tambem se voce esta chamando move_and_slide() no CharacterBody2D em vez de mexer direto na position.

Por que meu personagem escorrega ou desliza depois que solto a tecla?

Voce provavelmente nao esta zerando a velocity horizontal quando nao ha input. Use move_toward(velocity.x, 0, desaceleracao) ou defina velocity.x = 0 quando o eixo de input for zero. O move_and_slide() mantem a velocity que voce deixou, entao se voce nunca a reduz, o corpo continua andando.

move_and_slide() recebe a velocity como argumento no Godot 4?

Nao. No Godot 4 a velocity virou uma propriedade do proprio CharacterBody2D. Voce escreve velocity antes e chama move_and_slide() sem nenhum argumento. Isso mudou em relacao ao Godot 3, onde a velocidade era passada dentro do metodo.

Area2D serve para colisao solida?

Nao. Area2D detecta sobreposicao, mas nao empurra nada e nada bate nela como parede. Use Area2D para gatilhos: zona de dano, coleta de item, checkpoint, sensor de entrada. Para colisao solida use StaticBody2D, CharacterBody2D ou RigidBody2D.

Qual corpo usar para paredes e chao de um cenario?

StaticBody2D. Ele nao se move, serve de obstaculo solido e e o mais barato para a engine. Chao, paredes, plataformas fixas e limites do mapa sao casos classicos de StaticBody2D.