Voltar para o Blog
Quest Log

Como Fazer um Jogo de Plataforma 3D no Godot 4

Personagem cubico pulando entre plataformas flutuantes num cenario tridimensional colorido

Aprenda a fazer um jogo de plataforma 3D no Godot 4 do zero: CharacterBody3D, movimento, pulo, gravidade, coletaveis, camera e respawn com GDScript tipado.

Sair do 2D e montar seu primeiro jogo de plataforma 3D no Godot parece um salto enorme, mas na pratica voce reaproveita quase tudo que ja sabe. O que muda e a dimensao extra: um eixo a mais para o movimento, uma camera que vive no espaco e a fisica trabalhando com Vector3 em vez de Vector2. Neste tutorial voce vai construir, passo a passo, um personagem que anda, pula, coleta itens, segue uma camera decente e volta ao inicio quando cai do mapa. Todo o codigo esta em GDScript tipado, no padrao real do Godot 4.

Se voce ainda nao montou nada em 3D antes, vale dar uma olhada no primeiro jogo 3D no Godot para se ambientar com a viewport, os nos e a movimentacao de camera no editor. Aqui a gente parte do principio de que voce ja consegue criar uma cena e arrastar nos.

Montando o personagem com CharacterBody3D

O coracao de qualquer jogo de plataforma 3D no Godot e o no CharacterBody3D. Ele existe justamente para personagens que voce controla por codigo: detecta colisao, responde a rampas e degraus, mas nao vira um corpo fisico maluco quando encosta numa parede.

Crie uma cena nova com a seguinte estrutura:

  • CharacterBody3D (no raiz, renomeie para Jogador)
    • CollisionShape3D (dê uma CapsuleShape3D como forma)
    • MeshInstance3D (uma CapsuleMesh só para você enxergar o personagem)
    • SpringArm3D
      • Camera3D

A capsula e a escolha classica para personagens porque desliza bem por quinas e rampas. Configure o CollisionShape3D e a MeshInstance3D com aproximadamente a mesma altura e raio para o visual bater com a colisao.

Gravidade e pulo

Antes de andar, o personagem precisa cair. No Godot 4 a velocity e uma propriedade do proprio CharacterBody3D, e voce a modifica dentro de _physics_process. A gravidade e aplicada somando ao eixo Y a cada frame de fisica.

extends CharacterBody3D

var velocidade: float = 5.0
var forca_pulo: float = 8.0
var gravidade: float = 20.0

func _physics_process(delta: float) -> void:
    # Aplica gravidade quando esta no ar
    if not is_on_floor():
        velocity.y -= gravidade * delta

    # Pulo: so pula se estiver no chao
    if Input.is_action_just_pressed("ui_accept") and is_on_floor():
        velocity.y = forca_pulo

    move_and_slide()

Repare em tres detalhes que sao a cara do Godot 4: is_on_floor() retorna se o personagem esta apoiado, velocity e acessada direto (sem set_velocity) e move_and_slide() roda sem argumentos, usando a velocity interna. Nas versoes 3.x voce passava o vetor como parametro; no 4.x isso mudou e e um erro comum de quem migra tutoriais antigos.

Movimento com input e camera

Agora o personagem precisa andar nas quatro direcoes. O pulo dele e mapear as acoes de input para um vetor no plano do chao (eixos X e Z) e aplicar isso na velocity. O importante em 3D e que o movimento deve respeitar a direcao da camera: apertar "frente" leva o jogador para onde a camera aponta, nao sempre para o mesmo lado do mundo.

Primeiro, crie as acoes de input no menu Projeto, Configuracoes do Projeto, aba Mapa de Entrada: mover_frente, mover_tras, mover_esquerda, mover_direita. Depois expanda o _physics_process:

extends CharacterBody3D

@onready var mola_camera: SpringArm3D = $SpringArm3D

var velocidade: float = 5.0
var forca_pulo: float = 8.0
var gravidade: float = 20.0

func _physics_process(delta: float) -> void:
    if not is_on_floor():
        velocity.y -= gravidade * delta

    if Input.is_action_just_pressed("ui_accept") and is_on_floor():
        velocity.y = forca_pulo

    # Le o input como um vetor 2D e converte para direcao no espaco 3D
    var entrada: Vector2 = Input.get_vector(
        "mover_esquerda", "mover_direita",
        "mover_frente", "mover_tras"
    )
    var direcao: Vector3 = Vector3(entrada.x, 0.0, entrada.y)
    # Alinha o movimento com a orientacao da camera
    direcao = direcao.rotated(Vector3.UP, mola_camera.global_rotation.y)

    if direcao.length() > 0.0:
        velocity.x = direcao.x * velocidade
        velocity.z = direcao.z * velocidade
    else:
        # Freia suavemente quando nao ha input
        velocity.x = move_toward(velocity.x, 0.0, velocidade)
        velocity.z = move_toward(velocity.z, 0.0, velocidade)

    move_and_slide()

O Input.get_vector() ja normaliza a entrada, entao o personagem nao anda mais rapido na diagonal. E o rotated(Vector3.UP, ...) gira o vetor de movimento pelo angulo horizontal da camera, garantindo que "frente" seja sempre relativo ao que o jogador esta vendo.

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

A camera que segue o jogador com SpringArm3D

Uma camera fixa arruina um jogo de plataforma 3D. O SpringArm3D resolve isso de forma elegante: ele funciona como uma vara de pescar que segura a Camera3D a uma distancia definida e, se detectar uma parede no caminho, encurta automaticamente para a camera nao atravessar o cenario.

Configure no Inspetor do SpringArm3D:

  • Spring Length: a distancia da camera (algo como 4 a 6 funciona bem).
  • Posicione o no um pouco acima do centro do personagem, para a camera olhar de cima levemente.

Para o jogador controlar o giro da camera com o mouse, adicione ao script:

var sensibilidade: float = 0.005

func _unhandled_input(event: InputEvent) -> void:
    if event is InputEventMouseMotion:
        var mola: SpringArm3D = $SpringArm3D
        # Gira horizontalmente (eixo Y) e verticalmente (eixo X)
        mola.rotation.y -= event.relative.x * sensibilidade
        mola.rotation.x -= event.relative.y * sensibilidade
        # Trava o angulo vertical para nao capotar a camera
        mola.rotation.x = clamp(mola.rotation.x, deg_to_rad(-60), deg_to_rad(20))

Vale capturar o mouse no _ready() com Input.mouse_mode = Input.MOUSE_MODE_CAPTURED para o cursor ficar preso na janela enquanto o jogador olha ao redor.

Plataformas e colisao

As plataformas em que o jogador anda sao objetos estaticos. Use StaticBody3D para cada uma, com um CollisionShape3D (geralmente uma BoxShape3D) e uma MeshInstance3D para o visual. Como elas nao se movem por codigo, o StaticBody3D e a escolha mais barata em performance.

Um erro classico de iniciante e esquecer a colisao: se a plataforma so tem malha visual e nenhum CollisionShape3D, o personagem passa direto por ela e cai para sempre. Sempre confira se cada plataforma tem uma forma de colisao valida e ativada.

Para plataformas que se movem (elevadores, blocos que vao e voltam), use AnimatableBody3D em vez de StaticBody3D. Ele empurra o CharacterBody3D corretamente quando se move, coisa que um StaticBody3D animado nao faz de forma confiavel.

Coletaveis

Todo jogo de plataforma tem moedas, cristais ou estrelas para pegar. A ferramenta certa aqui e a Area3D, que detecta sobreposicao sem gerar colisao fisica. O jogador atravessa o coletavel e o item some, somando pontos.

Crie uma cena separada para o coletavel:

  • Area3D (raiz, renomeie para Moeda)
    • CollisionShape3D (uma SphereShape3D pequena)
    • MeshInstance3D (a malha da moeda)

E anexe este script a Area3D:

extends Area3D

signal coletado

func _ready() -> void:
    body_entered.connect(_ao_entrar)

func _ao_entrar(corpo: Node3D) -> void:
    if corpo.is_in_group("jogador"):
        coletado.emit()
        queue_free()

Para isso funcionar, adicione o CharacterBody3D do jogador ao grupo jogador (no editor, aba Node, Grupos). Assim a moeda so reage ao personagem, e nao a qualquer coisa que encoste nela. O queue_free() remove a moeda com seguranca no fim do frame, e o sinal coletado te permite atualizar um contador de pontos em outro script.

Respawn ao cair do mapa

Cair de uma plataforma faz parte do genero, mas o jogador nao pode despencar no infinito. A solucao mais simples e checar a altura do personagem a cada frame e reposiciona-lo quando ele passar de um limite.

Guarde a posicao inicial no _ready() e verifique a queda dentro do _physics_process:

var posicao_inicial: Vector3 = Vector3.ZERO
var altura_limite: float = -10.0

func _ready() -> void:
    posicao_inicial = global_position

func _verificar_queda() -> void:
    if global_position.y < altura_limite:
        global_position = posicao_inicial
        velocity = Vector3.ZERO

Chame _verificar_queda() no comeco do _physics_process. Zerar a velocity no respawn e essencial: sem isso, o personagem reaparece ja em alta velocidade de queda e afunda de novo. Numa versao mais polida, voce troca essa checagem por uma Area3D gigante embaixo do mapa que emite um sinal de respawn quando o jogador a toca, deixando o codigo do personagem mais limpo.

Proximos passos

Com essas pecas voce ja tem um jogo de plataforma 3D funcional no Godot 4: personagem, movimento relativo a camera, pulo, plataformas, coletaveis e respawn. A partir daqui da para adicionar dash, pulo duplo, inimigos com NavigationAgent3D, checkpoints e uma tela de vitoria quando todas as moedas forem pegas.

Se voce esta decidindo qual motor levar a serio para seus proximos projetos, vale ler nossa comparacao Godot vs Unity: comparacao completa e entender onde o Godot brilha em 3D. E, quando quiser saber se continua no GDScript ou parte para C#, o guia C# vs GDScript no Godot mostra os pros e contras de cada linguagem sem enrolacao.

Na CursoGame.Dev a gente acredita que o melhor jeito de aprender e colocando a mao no codigo. Monte esse projeto, quebre ele, conserte, e voce vai entender 3D no Godot de verdade.

Perguntas frequentes

Preciso saber fazer jogos 2D antes de partir pro 3D no Godot?

Ajuda, mas nao e obrigatorio. Os conceitos de input, colisao e fisica sao os mesmos. A maior diferenca e trabalhar com Vector3 em vez de Vector2 e lidar com uma camera que se move no espaco. Se voce ja fez algo simples em 2D, a transicao pro 3D vai fluir rapido.

Qual no eu uso pro personagem de plataforma 3D no Godot 4?

Use CharacterBody3D. Ele foi feito para personagens controlados por codigo que precisam de deteccao de colisao e resposta a fisica, mas sem simulacao completa de corpo rigido. A propriedade velocity combinada com move_and_slide() cuida do movimento e das colisoes com o cenario.

Como faco a camera seguir o jogador em 3D?

A forma mais robusta e usar um SpringArm3D como filho do personagem, com a Camera3D presa na ponta do braco. O SpringArm3D encurta automaticamente quando ha uma parede entre a camera e o jogador, evitando que a camera atravesse geometria.

Por que meu personagem cai atravessando o chao no Godot?

Quase sempre e colisao mal configurada. Verifique se o personagem tem um CollisionShape3D valido, se as plataformas tem StaticBody3D com colisao e se as camadas de colisao (layers e masks) estao coerentes. Um CollisionShape3D vazio ou desativado faz o corpo cair pra sempre.

Como funciona o respawn quando o jogador cai do mapa?

Voce checa a posicao Y do personagem a cada frame. Se ela ficar abaixo de um limite (por exemplo -10), voce reposiciona o personagem no ponto inicial e zera a velocity. Uma alternativa mais elegante e usar uma Area3D grande embaixo do mapa que dispara o respawn ao ser tocada.

Devo usar GDScript ou C# pra fazer jogo de plataforma 3D?

Para aprender e prototipar, GDScript e o caminho mais direto, pois e integrado ao editor e tem menos atrito. C# faz sentido quando o projeto cresce ou quando voce ja domina a linguagem. Os dois acessam a mesma API do Godot, entao a logica deste tutorial vale para ambos.