Voltar para o Blog
Quest Log

GDExtension na Godot 4: Quando Usar C++ em Vez de GDScript

Tela dividida mostrando um editor de codigo com script ao lado de um terminal compilando uma biblioteca nativa

GDExtension e C++ na Godot 4: entenda o que muda em relacao ao GDScript e o criterio honesto para saber se o seu jogo realmente precisa de codigo nativo.

Voce ja programa em GDScript, viu alguem falar de GDExtension e C++ na Godot 4 e ficou com a duvida: eu preciso disso? A resposta curta e honesta: quase certamente nao. A grande maioria dos jogos feitos na Godot roda inteira em GDScript sem nenhum problema de performance. Mas existe um punhado de situacoes reais em que descer para codigo nativo faz diferenca, e vale entender quais sao para nao ficar nem paranoico nem ingenuo. Este post explica o que e GDExtension, como o fluxo com C++ funciona na pratica e, principalmente, o criterio para decidir.

O que e GDExtension (e o que mudou desde o GDNative)

GDExtension e o mecanismo oficial da Godot 4 para carregar uma biblioteca nativa compilada (um .dll, .so ou .dylib) direto na engine, em tempo de execucao, sem recompilar a Godot. Voce baixa o binario oficial da engine, aponta um arquivo de configuracao para a sua biblioteca e pronto: suas classes em C++ aparecem no editor como se fossem tipos nativos.

Isso e diferente de duas coisas que confundem bastante:

  • Modulo de engine: exige clonar o codigo-fonte da Godot, escrever o codigo dentro dele e recompilar a engine inteira. Voce passa a distribuir um binario customizado. Poderoso, mas pesado de manter.
  • GDNative (Godot 3): era a geracao anterior dessa mesma ideia. GDExtension e o sucessor, com uma interface mais estavel e melhor integracao com o editor.

A sacada e essa: com GDExtension voce ganha velocidade de codigo nativo mantendo a Godot oficial, sem fork da engine. O preco e ter uma etapa de compilacao C++ no seu projeto, com tudo que isso implica de toolchain, tempo de build e um binario por plataforma.

Antes de C++, esgote o GDScript tipado

O erro mais comum e pular direto para C++ achando que GDScript e lento por natureza. GDScript tipado (com anotacoes de tipo em tudo) e consideravelmente mais rapido que o dinamico, porque o interpretador evita boa parte das checagens em tempo de execucao. Muita gente que reclama de performance simplesmente nunca tipou o codigo.

Veja um exemplo de algo que parece pesado, uma simulacao de particulas numa CPU:

extends Node

var posicoes: PackedVector2Array = PackedVector2Array()
var velocidades: PackedVector2Array = PackedVector2Array()
var gravidade: Vector2 = Vector2(0.0, 98.0)

func _ready() -> void:
    posicoes.resize(50000)
    velocidades.resize(50000)

func _physics_process(delta: float) -> void:
    var total: int = posicoes.size()
    for i: int in range(total):
        velocidades[i] += gravidade * delta
        posicoes[i] += velocidades[i] * delta

Esse loop, tipado e com PackedVector2Array, ja roda muito melhor do que a versao ingenua com Array dinamico. Para dezenas de milhares de elementos por frame ele pode segurar, e antes de reescrever qualquer coisa vale revisar as tecnicas gerais para otimizar a performance e manter 60 FPS. Se o problema for so que a logica roda na mesma thread do jogo, talvez a solucao nem seja C++, e sim usar multiplas threads com o WorkerThreadPool para tirar o calculo do caminho critico do frame.

So depois de tipar, medir com o profiler e ainda encontrar um loop apertado que estoura o orcamento de frame e que a decisao por C++ comeca a fazer sentido.

Quando C++ via GDExtension realmente entra

Ha tres casos honestos onde o codigo nativo compensa:

  1. Simulacao numerica pesada: fisica customizada, fluidos, muitos agentes com IA por frame, calculo que roda centenas de milhares de vezes num loop apertado.
  2. Geracao procedural intensa: ruido, marching cubes, geracao de mundo ou malhas em runtime onde o custo esta no calculo puro, nao no desenho.
  3. Integrar uma biblioteca C ou C++ que ja existe: um decodificador, um motor de fisica externo, um SDK nativo. Aqui C++ nao e sobre velocidade, e a unica ponte pratica.

Fora disso, a resposta costuma ser nao. Se o seu gargalo e quantidade de nos na cena, chamadas de desenho ou fisica da propria engine, reescrever a sua logica em C++ nao vai resolver, porque o custo esta noutro lugar. Vale lembrar tambem que existe um meio-termo: se o incomodo com GDScript for mais sobre organizacao e tipagem forte do que sobre velocidade bruta, a comparacao entre C# e GDScript na Godot mostra uma opcao com performance melhor que GDScript e complexidade de build bem menor que C++.

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

Como e o fluxo com godot-cpp na pratica

A biblioteca oficial de bindings chama godot-cpp. Ela expoe a API da engine para C++ e e o ponto de partida de qualquer GDExtension. O fluxo geral, sem entrar em cada detalhe de sistema operacional, e este:

  1. Clonar o godot-cpp no branch que corresponde a sua versao da Godot (importante: os bindings sao versionados junto com a engine).
  2. Escrever suas classes em C++, herdando de tipos da engine como RefCounted, Node ou Node2D.
  3. Compilar com SCons (o SConstruct do godot-cpp cuida disso), gerando a biblioteca nativa para cada plataforma alvo.
  4. Criar o arquivo .gdextension, que diz a engine qual binario carregar em cada plataforma e qual e o ponto de entrada.
  5. Abrir o projeto na Godot: suas classes aparecem no editor e podem ser usadas por nos e por GDScript normalmente.

O .gdextension e um arquivo de texto simples com uma secao de configuracao e um mapa de bibliotecas por plataforma. E ele que amarra o binario compilado a engine oficial.

Registrar uma classe e expor um metodo

O coracao de uma GDExtension e o registro da classe e dos metodos que voce quer chamar de fora. A Godot usa a ClassDB para isso, e cada classe declara os seus bindings num metodo estatico _bind_methods. Veja uma versao minima e realista de uma classe que estende RefCounted e expoe um metodo de calculo:

// particulas.h
#ifndef PARTICULAS_H
#define PARTICULAS_H

#include <godot_cpp/classes/ref_counted.hpp>

namespace godot {

class Particulas : public RefCounted {
    GDCLASS(Particulas, RefCounted)

private:
    float gravidade = 98.0f;

protected:
    static void _bind_methods();

public:
    void set_gravidade(float valor);
    float get_gravidade() const;
    float passo(float delta, float velocidade) const;
};

}

#endif

E a implementacao, onde os bindings sao declarados de fato:

// particulas.cpp
#include "particulas.h"
#include <godot_cpp/core/class_db.hpp>

using namespace godot;

void Particulas::_bind_methods() {
    ClassDB::bind_method(D_METHOD("passo", "delta", "velocidade"),
            &Particulas::passo);
    ClassDB::bind_method(D_METHOD("set_gravidade", "valor"),
            &Particulas::set_gravidade);
    ClassDB::bind_method(D_METHOD("get_gravidade"),
            &Particulas::get_gravidade);
    ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "gravidade"),
            "set_gravidade", "get_gravidade");
}

void Particulas::set_gravidade(float valor) {
    gravidade = valor;
}

float Particulas::get_gravidade() const {
    return gravidade;
}

float Particulas::passo(float delta, float velocidade) const {
    return velocidade + gravidade * delta;
}

Repare em alguns pontos que sao reais e importantes:

  • GDCLASS(Particulas, RefCounted) declara a classe para o sistema de tipos da Godot.
  • D_METHOD("passo", "delta", "velocidade") da o nome do metodo e os nomes dos argumentos como aparecem para o GDScript.
  • ClassDB::bind_method liga o nome exposto ao ponteiro do metodo real em C++.
  • ADD_PROPERTY transforma um par de getter e setter numa propriedade visivel no editor.

Falta um pedaco de cola: o arquivo de inicializacao, geralmente register_types.cpp, onde voce chama GDREGISTER_CLASS(Particulas) dentro da funcao de inicializacao do modulo, no nivel de cena. E esse ponto de entrada que o .gdextension referencia. Depois de compilado, o uso a partir do GDScript fica banal e totalmente tipado:

extends Node

func _ready() -> void:
    var sim: Particulas = Particulas.new()
    sim.gravidade = 120.0
    var nova_vel: float = sim.passo(0.016, 0.0)
    print(nova_vel)

Ou seja: o jogo continua em GDScript, e so o miolo do calculo mora em C++. Esse e o padrao saudavel. Voce nao reescreve o jogo, voce cirurgicamente move o gargalo.

Criterios claros de decisao

Antes de abrir o godot-cpp, passe por esta lista honesta:

  • Voce ja tipou todo o codigo do trecho lento? Se nao, faca isso primeiro. E de graca.
  • Voce mediu com o profiler? Precisa saber que o gargalo e o seu loop de calculo, e nao desenho ou fisica da engine.
  • O custo esta em calculo puro repetido muitas vezes por frame? Esse e o cenario onde C++ ganha de verdade.
  • O gargalo poderia sair da thread principal? As vezes o problema e concorrencia, nao linguagem.
  • Voce precisa integrar uma biblioteca nativa existente? Ai C++ nao e otimizacao, e a ponte necessaria.
  • Voce vai exportar para web? Confirme o suporte de WebAssembly antes de amarrar o projeto a GDExtension.

Se voce respondeu nao para as primeiras e nao tem uma biblioteca nativa para integrar, provavelmente nao precisa de C++. E isso e uma boa noticia: significa menos toolchain, builds mais rapidos, um binario a menos por plataforma e um projeto mais facil de manter.

Fechando

GDExtension e uma das melhores partes da Godot 4: da acesso a performance nativa sem forkar a engine, e deixa voce misturar C++ e GDScript com liberdade. Mas ela e uma ferramenta de precisao, nao um upgrade geral. Os 95% dos jogos que nao tem simulacao pesada, geracao procedural intensa nem biblioteca nativa para integrar vivem otimamente com GDScript bem tipado. Aprenda a reconhecer o gargalo real antes de escrever a primeira linha de C++, e quando ele aparecer, voce vai saber exatamente onde aplicar o bisturi.

Perguntas frequentes

Preciso saber C++ para fazer jogo na Godot?

Nao. A imensa maioria dos jogos publicados na Godot roda so com GDScript. C++ via GDExtension e uma ferramenta para casos especificos de performance ou integracao de bibliotecas nativas. Se voce esta comecando, aprender GDScript tipado bem feito vale muito mais do que correr atras de C++.

GDExtension e a mesma coisa que criar um modulo ou recompilar a engine?

Nao. Modulo de engine exige recompilar a Godot inteira e distribuir um binario customizado. GDExtension carrega uma biblioteca nativa ja compilada em tempo de execucao, usando a Godot oficial sem alteracao. E o sucessor do antigo GDNative e bem mais pratico de manter.

Da para misturar C++ e GDScript no mesmo projeto?

Sim, esse e justamente o ponto forte. Voce registra classes em C++ que aparecem no editor como se fossem tipos nativos e usa elas a partir de nos e scripts em GDScript. O comum e manter o jogo em GDScript e descer para C++ so nos poucos pontos que pedem.

GDExtension deixa o jogo mais rapido sempre?

Nao. Codigo nativo ajuda em trechos com muito calculo em loop apertado. Se o gargalo e desenho, fisica da engine ou logica que roda poucas vezes por frame, reescrever em C++ nao muda quase nada e ainda adiciona complexidade de build. Meça antes de decidir.

GDExtension funciona no export mobile e web?

Mobile (Android e iOS) funciona, desde que voce compile a biblioteca para cada plataforma alvo. Web (WebAssembly) e o caso mais delicado: exige toolchain especifica e nem toda GDExtension tem build pronto para essa plataforma. Confirme o suporte antes de depender de C++ se o export web for obrigatorio.