Voltar para o Blog
Quest Log

Migrar Projeto do Godot 3 para o Godot 4: Guia Prático de Conversão

Ilustração de um projeto de jogo sendo transferido do Godot 3 para o Godot 4

Guia prático para migrar Godot 3 para 4: conversor automático, renomeações de nodes, GDScript 2.0 e os breaking changes que o conversor não resolve.

Migrar Projeto do Godot 3 para o Godot 4: Guia Prático de Conversão

Migrar Godot 3 para 4 não é apertar um botão e torcer. O Godot 4 mudou renderer, reorganizou a árvore de nodes, renomeou centenas de classes e reescreveu o GDScript. O conversor automático que vem na engine resolve a parte chata (as renomeações em massa), mas deixa pra você tudo que envolve lógica: sinais, corrotinas, física de personagem, shaders.

A boa notícia: o processo tem um caminho conhecido. Esse guia segue a ordem que funciona na prática: decidir se vale migrar, preparar o projeto, rodar o conversor, e então atacar os breaking changes que sobram, um por um, com o antes e depois em código.

Vale a pena migrar?

Resposta honesta: depende de onde o projeto está.

Migre se: o projeto está no começo ou no meio do desenvolvimento, você vai dar suporte a ele por anos, ou precisa de algo que só existe no 4 (o renderer Forward+ com Vulkan, o GDScript 2.0 com tipagem melhor, a física Jolt no 3D).

Não migre se: o jogo está a semanas do lançamento. Migração de engine na reta final é receita pra atrasar tudo e introduzir bug em sistema que já estava estável. Termine no 3.x, lance, e migre na sequência (ou no próximo projeto).

Pondere se: o projeto depende pesado de plugins de terceiros. Addon do Godot 3 não roda no 4, e nem todo autor portou o dele. Antes de qualquer coisa, abra a pasta addons/ e confira plugin por plugin se existe versão pro Godot 4. Se um plugin central do seu jogo não tem porte, esse é o seu custo real de migração, não o resto.

Sobre o tamanho do trabalho: projeto pequeno e organizado migra em horas. Projeto grande, com muito script acoplado e shader customizado, leva dias. A variável que mais pesa é quanto código GDScript você tem, porque é nele que o conversor menos ajuda.

Preparação: antes de rodar qualquer conversor

Três passos antes de encostar no Godot 4:

  1. Atualize pro último 3.x. O conversor foi pensado pra projetos vindos da série 3.x recente. Se o projeto está no 3.2 ou 3.3, suba primeiro pro 3.5/3.6 dentro da própria série 3, resolva o que quebrar aí (vai ser pouco), e só então parta pro 4.
  2. Commit limpo no Git. O conversor reescreve arquivos no lugar, sem desfazer. Você quer um git status limpo antes, pra poder comparar cada mudança no diff e voltar atrás se precisar. Se o projeto não está em versionamento, esse é o momento de corrigir isso (ou no mínimo duplicar a pasta inteira).
  3. Liste seus pontos críticos. Anote onde o projeto usa yield, setget, Tween, File/Directory e shaders customizados. São exatamente os pontos onde o conversor vai te deixar na mão, e ter a lista pronta transforma a migração de caça ao tesouro em checklist.

Como migrar Godot 3 para 4 com o conversor automático

O Godot 4 traz um conversor de projetos embutido. Ele varre cenas (.tscn), recursos (.tres), scripts (.gd) e configurações, aplicando as renomeações de classes, métodos, propriedades e sinais da versão nova.

Dois jeitos de rodar:

Pelo Project Manager: abra o Godot 4, importe o project.godot do projeto antigo, e o editor oferece a conversão completa antes de abrir. É o caminho mais simples.

Pela linha de comando, que eu prefiro porque permite validar antes de alterar. Na pasta do projeto, com o executável do Godot 4:

# Primeiro: simula a conversão e lista o que seria alterado, sem tocar em nada
godot --validate-conversion-3to4

# Depois de revisar a saída: converte de verdade
godot --convert-3to4

Leia a saída do --validate-conversion-3to4 com atenção. Ela mostra arquivo por arquivo o que vai mudar, e é onde você descobre surpresas antes delas acontecerem. Detalhe que pega gente: por segurança, o conversor pula arquivos muito grandes e linhas muito longas por padrão. Se você tem um .tscn gigante ou um script com linhas quilométricas, confira no log se algo foi pulado e ajuste os limites passando os argumentos max_file_kb e max_line_size na chamada.

O que o conversor cobre bem

A força dele é renomeação em massa. Os casos mais comuns que ele resolve sozinho:

Godot 3Godot 4
SpatialNode3D
KinematicBody2DCharacterBody2D
KinematicBodyCharacterBody3D
AreaArea3D
RayCastRayCast3D
Position2DMarker2D
instance()instantiate()
OS.get_ticks_msec()Time.get_ticks_msec()
deg2rad() / rad2deg()deg_to_rad() / rad_to_deg()
rand_range()randf_range()
stepify()snapped()
export var@export var
onready var@onready var

O padrão geral das classes 3D: tudo que não tinha sufixo ganhou 3D (porque Spatial virou Node3D e a família inteira seguiu). Já as keywords do GDScript viraram annotations com @: export, onready, tool viraram @export, @onready, @tool.

Depois de rodar, abra o diff no Git e passe o olho. O conversor é conservador e às vezes deixa um comentário ou um trecho marcado em vez de converter. Cada um desses merece revisão manual.

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

Os breaking changes que sobram pra você

Aqui começa o trabalho de verdade. O conversor renomeia, mas não reescreve lógica. Esses são os pontos que você vai corrigir na mão, em ordem de frequência.

Sinais: conexão e await

A sintaxe de sinal mudou por completo. No Godot 3, tudo era string. No 4, sinal é objeto de primeira classe e a conexão recebe um Callable:

# Godot 3
button.connect("pressed", self, "_on_button_pressed")
emit_signal("game_over")

# Godot 4
button.pressed.connect(_on_button_pressed)
game_over.emit()

A versão nova é melhor em tudo: o editor autocompleta, e erro de digitação no nome do sinal vira erro de parse em vez de bug silencioso em runtime.

yield virou await

O yield não existe mais. Esperar um sinal agora é await direto no sinal:

# Godot 3
yield(get_tree().create_timer(1.0), "timeout")
yield(tween, "finished")

# Godot 4
await get_tree().create_timer(1.0).timeout
await tween.finished

O conversor tenta ajudar nos casos simples, mas qualquer uso de yield como corrotina manual (retomar função com resume, por exemplo) precisa ser repensado, porque o modelo de corrotina mudou. Procure todos os yield do projeto antes de rodar o conversor e marque os que fazem algo além de "esperar sinal".

move_and_slide e a velocity embutida

Quem tem jogo de plataforma sente essa primeiro. No Godot 3, você mantinha sua própria variável de velocidade e passava pro move_and_slide(), que devolvia a velocidade ajustada. No 4, velocity é propriedade do próprio CharacterBody e o método não recebe nem retorna nada:

# Godot 3 (KinematicBody2D)
var velocity = Vector2.ZERO

func _physics_process(delta):
    velocity.y += gravity * delta
    velocity = move_and_slide(velocity, Vector2.UP)

# Godot 4 (CharacterBody2D)
func _physics_process(delta):
    velocity.y += gravity * delta
    move_and_slide()

A direção "pra cima" que era o segundo argumento virou a propriedade up_direction, que no 2D já vem com o padrão certo. Se o seu script declarava var velocity, delete a declaração: ela agora conflita com a propriedade nativa.

setget virou set/get inline

A keyword setget sumiu. Setter e getter agora moram junto da declaração da variável:

# Godot 3
var health = 100 setget set_health

func set_health(value):
    health = clamp(value, 0, 100)

# Godot 4
var health = 100:
    set(value):
        health = clamp(value, 0, 100)

Diferença de comportamento que importa: no Godot 3, atribuição dentro do próprio script não passava pelo setter (só acesso externo passava). No 4, o setter roda sempre, inclusive em atribuição interna. Se algum setter seu tem efeito colateral pesado, revise quem atribui nessa variável.

Tween virou objeto, não node

O node Tween que você adicionava na cena não existe mais. Tween agora é criado por código, na hora de usar:

# Godot 3 (node Tween na cena)
$Tween.interpolate_property(self, "position", position, target, 0.5,
    Tween.TRANS_QUAD, Tween.EASE_OUT)
$Tween.start()

# Godot 4
var tween = create_tween()
tween.tween_property(self, "position", target, 0.5).set_trans(Tween.TRANS_QUAD).set_ease(Tween.EASE_OUT)

Além de mais curto, o tween novo se libera sozinho quando termina. O conversor não faz essa migração: ele não tem como saber a intenção da animação. É reescrita manual, mas das gostosas, porque o código sempre encolhe.

File e Directory viraram FileAccess e DirAccess

Acesso a arquivo mudou de "instancia e abre" pra método estático que já devolve o handle aberto:

# Godot 3
var file = File.new()
file.open("user://save.dat", File.READ)
var data = file.get_as_text()
file.close()

# Godot 4
var file = FileAccess.open("user://save.dat", FileAccess.READ)
var data = file.get_as_text()
# fecha sozinho quando a referência sai de escopo

Mesmo padrão pro Directory, que virou DirAccess. Todo sistema de save/load passa por aqui, então teste salvar e carregar logo depois de migrar essa parte.

Shaders e renderer

O conversor não toca em shader, e a linguagem mudou em pontos importantes: hint_albedo virou source_color, vários nomes de matriz e de funções built-in mudaram. Shader simples se corrige rápido lendo o erro que o editor cospe; shader complexo merece uma sessão dedicada.

No renderer, a escolha GLES2/GLES3 deixou de existir. O Godot 4 oferece Forward+ (desktop, o mais completo), Mobile (otimizado pra celular) e Compatibility (OpenGL, roda em hardware antigo e web). A conversão não escolhe por você: pense no seu alvo. Jogo 2D pra web e mobile costuma ficar bem no Compatibility; 3D de desktop pede Forward+. E aceite desde já que luz e pós-processamento vão ficar diferentes do que estavam no 3: reserve um tempo pra reajustar iluminação e environment olhando o jogo, não os números antigos.

Checklist pós-conversão

Depois do conversor e das correções manuais, rode essa sequência antes de considerar a migração fechada:

  1. Abra cena por cena no editor. Cena que quebrou aparece com erro de dependência na hora. Resolva antes de rodar o jogo.
  2. Procure os avisos do conversor. Busque no projeto por comentários e trechos que ele marcou em vez de converter.
  3. Rode o jogo e jogue de verdade. Movimento, colisão, UI, save/load, áudio. Os bugs de migração adoram se esconder em fluxo que você não testa há meses.
  4. Revise os exports. As configurações de export mudaram entre as versões; reconfigure os presets de cada plataforma e gere uma build de teste em todas.
  5. Confira a iluminação. Principalmente em 3D, compare lado a lado com a versão antiga e reajuste o que mudou de cara.

Fechando

Migrar Godot 3 para 4 é um projeto curto, não um clique. O caminho que funciona: decidir com calma se é a hora, garantir backup e a lista de pontos críticos, deixar o conversor fazer a renomeação em massa, e então resolver na mão sinais, await, move_and_slide, setget, Tween, arquivos e shaders, testando a cada bloco.

O esforço se paga. O GDScript 2.0 é mais rápido e mais seguro de escrever, o editor é melhor, e é no 4 que a engine evolui daqui pra frente. Se o seu projeto tem futuro, ele merece estar onde o futuro da engine está.