~3 мин чтения

GDExtension — нативные плагины на C++ и Rust

godot-cpp, gdext (Rust), когда нужны нативные расширения, как они работают.

GDScript хорош для большинства gameplay-логики, но иногда нужно опуститься ниже:

  • Воксельный движок с миллионами блоков
  • Custom shading в реальном времени с сложной CPU-математикой
  • Интеграция со существующей C/C++ библиотекой (физика, NN inference, audio DSP)
  • Performance hot path, где даже static-typed GDScript не справляется

GDExtension — современный способ расширять Godot на нативном уровне. Заменил GDNative с Godot 4.0.

Главные идеи

  • Вы пишете код в C++ (через godot-cpp) или Rust (через gdext).
  • Компилируете в dynamic library (.so / .dll / .dylib).
  • Создаёте манифест .gdextension, который Godot загружает при старте.
  • В редакторе ваши классы появляются как обычные узлы — добавляются в сцену, имеют свойства в Inspector, можно подключать сигналы.

Главное преимущество GDExtension над модулями (которые в monorepo Godot): не нужно пересобирать сам редактор. Меняете плагин → reload Godot → новая версия работает.

Веб

Node native modules (.node файлы через node-gyp). Или WASM-модули, скомпилированные из Rust/C++ для браузера.

Unity

Структура GDExtension-плагина

my_plugin/
├── my_plugin.gdextension          ← манифест
├── src/
│   ├── register_types.cpp         ← регистрация классов
│   ├── my_node.cpp
│   └── my_node.h
├── bin/                           ← собранные .so/.dll
│   ├── libmyplugin.linux.x86_64.so
│   ├── libmyplugin.windows.x86_64.dll
│   └── libmyplugin.macos.universal.dylib
├── SConstruct                     ← сборка через SCons
└── godot-cpp/                     ← submodule с биндингами

my_plugin.gdextension:

[configuration]
entry_symbol = "myplugin_library_init"
compatibility_minimum = "4.4"

[libraries]
linux.x86_64 = "bin/libmyplugin.linux.x86_64.so"
windows.x86_64 = "bin/libmyplugin.windows.x86_64.dll"
macos = "bin/libmyplugin.macos.universal.dylib"

Минимальный пример на C++

my_node.h:

#ifndef MY_NODE_H
#define MY_NODE_H

#include <godot_cpp/classes/node3d.hpp>

namespace godot {

class MyNode : public Node3D {
    GDCLASS(MyNode, Node3D)

private:
    double speed = 1.0;

protected:
    static void _bind_methods();

public:
    MyNode();
    ~MyNode();

    void _process(double delta) override;

    void set_speed(double p_speed);
    double get_speed() const;
};

}

#endif

my_node.cpp:

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

using namespace godot;

void MyNode::_bind_methods() {
    ClassDB::bind_method(D_METHOD("set_speed", "p_speed"), &MyNode::set_speed);
    ClassDB::bind_method(D_METHOD("get_speed"), &MyNode::get_speed);
    ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "speed"), "set_speed", "get_speed");
}

MyNode::MyNode() {}
MyNode::~MyNode() {}

void MyNode::_process(double delta) {
    rotate_y(speed * delta);
}

void MyNode::set_speed(double p_speed) { speed = p_speed; }
double MyNode::get_speed() const { return speed; }

После компиляции (scons → бинарь в bin/) → перезапуск Godot → “MyNode” появится в Add Node с полем speed в Inspector.

Rust — gdext

Сообщество разработало gdext — биндинги для Rust. Стиль более идиоматичный:

use godot::prelude::*;

struct MyExtension;

#[gdextension]
unsafe impl ExtensionLibrary for MyExtension {}

#[derive(GodotClass)]
#[class(base=Node3D)]
struct MyNode {
    #[var]
    speed: f64,
    base: Base<Node3D>,
}

#[godot_api]
impl INode3D for MyNode {
    fn init(base: Base<Node3D>) -> Self {
        Self { speed: 1.0, base }
    }

    fn process(&mut self, delta: f64) {
        let rotation_y = self.base().get_rotation().y + (self.speed * delta) as f32;
        let mut rot = self.base().get_rotation();
        rot.y = rotation_y;
        self.base_mut().set_rotation(rot);
    }
}

Rust-преимущества:

  • Memory safety без overhead — нет malloc/free ошибок, нет UB.
  • Cargo — экосистема пакетов проще, чем CMake/SCons для C++.
  • Performance на уровне C++.

Минусы:

  • Чуть медленнее компиляция первого раза.
  • Меньше community-плагинов с примерами (чем C++).

gdext активно развивается и считается production-ready на 2026 год.

Когда стоит писать GDExtension

Стоит:

  • Voxel-engine, terrain LOD, marching cubes.
  • Custom physics constraints или soft-body симуляция.
  • Real-time DSP / audio synthesis.
  • Интеграция со существующей C++ библиотекой (Open3D, OpenCV, библиотеки ML inference).
  • Workflows, где даже Burst/SIMD-уровень GDScript недостаточен.

НЕ стоит:

  • Стандартная gameplay-логика (используйте GDScript).
  • Single-shot операции (один раз сгенерировать карту — пишите в WorkerThreadPool из GDScript).
  • Когда не уверены, что узкое место именно в CPU вычислениях. Профайлите сначала.

Производительность

Бенчмарки для простого numerical workload (миллион итераций):

ЯзыкВремя
GDScript (untyped)850 мс
GDScript (typed)400 мс
C#80 мс
C++ (GDExtension)12 мс
Rust (gdext)12 мс

C++ и Rust — в десятки раз быстрее typed GDScript. Но overhead начинается при пересечении GDExtension boundary (вызов C++ метода из GDScript). Поэтому пишут большие куски в C++, вызывая редко.

Кросс-платформа — собирайте под каждую платформу отдельно

GDExtension — это нативные бинарники. Linux x86_64 не работает на Windows. Нужно собирать под каждую target-платформу, что усложняет CI/CD. Для одной платформы — просто; для shipping в Windows + Linux + macOS + Android + iOS — нужны 5 разных CI-job’ов.

Расширения, которые часто пишут на GDExtension

  • godot-rapier-3d — Rapier physics на Rust (альтернатива встроенной физике).
  • Voxelity — voxel engine для Godot.
  • godot-luau-script — Luau (Roblox-style) скриптинг.
  • NAVigator — продвинутая навигация.

В Asset Library есть категория “Native plugins” — там готовые GDExtension-плагины.

Альтернатива — C# в Godot

Если у вас .NET-команда и не хочется лезть в C++, C# через Godot.NET даёт ~10× ускорение над GDScript (untyped). См. следующую главу.

Сравнение с Unity

Unity-аналог:

  • Native Plugin (.dll / .dylib / .so) загружается через [DllImport].
  • Менее интегрированно — нативные плагины не появляются как Node-классы в иерархии.
  • Альтернатива в Unity для тяжёлых вычислений — Job System + Burst (см. главу про Jobs+Burst), всё внутри C# и без выхода в нативный мир.

GDExtension в Godot — более глубокая интеграция с движком; Burst в Unity — оптимизация без выхода из C#. Оба подхода правомерны.