GD++ is a programming language for Godot. It compiles to C++, and plugs into Godot through GDExtension. It's inspired by the conciseness and simplicity of GDScript.
GD++ looks like GDScript declarations, with C++ implementation. But it is neither GDScript nor C++:
- Declarations are transpiled into C++ code that targets GDExtension via godot-cpp.
- Function bodies are flavoured C++: C++ with a few custom quality of life features.
GD++ toolchain comes as one command line tool, gd++: the compiler, a build system that downloads required build dependencies for you, and a built-in manual.
See the GD++ sources of the Foliage3D addon for a real-life project written entirely in GD++.
Note
Disclaimer: The code was mostly written by AI, but a senior engineer made all design decisions.
Save it as hello_world.gd++ (or any other name with extension any of .gd++, .gdpp or .gg) anywhere in a Godot project, and run:
gd++ init . --bind 10.0.0-stable --spec 4.7.2-stable # Replace this with the versions you're using.
gd++ fetch --missing
gd++ buildOpen the project in Godot: HelloWorldNode is now a node type.
Add it to the main scene and run it.
You need Godot 4, and Go to build gd++ itself:
make && sudo make install # builds gd++ and copies it to /usr/local/binThen install the tools that compile C++ (Git, SCons, Python and a C++ compiler):
gd++ install # asks before running anything
gd++ install --echo # or just prints the commands, to run them yourselfgd++ install supports Debian, Ubuntu, Fedora, Arch, openSUSE, macOS (with Homebrew) and Windows (with winget). It's experimental, and hasn't been tested on every platform. On Linux and macOS, it also installs MinGW-w64, to build for Windows.
The full documentation is built into the tool, and matches the version you run. Run gd++ man to list its pages, and start with gd++ man intro and gd++ man lang.
Blocks use braces, and every value has a static Godot type. Most examples show a few members of a class.
See gd++ man classes and gd++ man includes.
See gd++ man functions.
See gd++ man variables.
See gd++ man signals.
See gd++ man signals.
See gd++ man exports.
See gd++ man functions.
See gd++ man enums.
See gd++ man enums.
See gd++ man variables.
See gd++ man variables.
Callbacks are on blocks: code that the engine runs for an object, at a notification like these, at a signal (see Signal handlers), or for a property (see Property callbacks).
See gd++ man callbacks.
See gd++ man functions.
See gd++ man types.
See gd++ man classes and gd++ man gd.
See gd++ man cast.
See gd++ man rewrites.
See gd++ man docs.
See gd++ man functions.
See gd++ man exports.
See gd++ man functions.
See gd++ man lifecycle.
See gd++ man functions.
See gd++ man functions.
See gd++ man async.
Like GDScript's await. Scripts await a task with await task.until_done().
See gd++ man async.
Shaders are functions written in GLSL, which run on the GPU. Without one, e.g. on a dedicated server, they run on the CPU. A call waits for results that come back to the CPU, e.g. an Image, and returns others right away. With @async, it returns an Async instead, which is done once the GPU is.
See gd++ man shaders.
See gd++ man rewrites.
See gd++ man callbacks.
See gd++ man classes.
See gd++ man classes.
See gd++ man project-names.
See gd++ man classes.
See gd++ man classes.
See gd++ man enums.
See gd++ man traits.
See gd++ man structs.
See gd++ man types.
See gd++ man rpc.
See gd++ man pools.
With gd++ build --trace Player, the game prints:
[f812] ▶ Player "Hero".take_damage(amount: 5)
[f812] Player "Hero".health: 100 → 95 (in take_damage)
[f812] ◀ Player "Hero".take_damage → false 12.4 µs
See gd++ man debugging.
With gd++ build --profile ai --print, the game prints a table every 10 seconds:
━━ GD++ profile · last 10.0 s · 600 frames · debug, unoptimized ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Function Thread Calls Total ms Self ms Avg µs Max µs ms/frame Budget (60 FPS)
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Soldier.find_cover main 1200 846.31 846.31 705.26 4210.55 1.411 8.5%
Soldier.pick_target main 600 41.82 41.82 69.70 290.04 0.070 0.4%
See gd++ man debugging.
gd++ test builds the package, and runs the tests of its @test classes in a headless Godot. Only it registers them, and release builds leave them out:
[•] Testing res://.
[•] Passed WalletTest.pays in 0.1 ms.
[•] All 1 test passed.
See gd++ man tests.
See gd++ man externs.
See gd++ man runtime.
See gd++ man code.
See gd++ man includes.
See gd++ man templates.
See gd++ man macros.
See gd++ man annotations.
- A project is a normal Godot project.
- A package is a directory with a
.gd++pkgfile. It builds into one GDExtension library. - Dependencies are the Godot C++ bindings (godot-cpp), the Godot API specs, and the Godot engines that run tests.
gd++ init --vcs git # keep GD++'s files out of git
gd++ init . --bind 10.0.0-stable --spec 4.7.2-stable # make the project root a package
gd++ init tools --bind 10.0.0-stable --spec 4.7.2-stable # or add a package anywhere
gd++ fetch --index # list the dependencies that are available
gd++ fetch --missing # download what the packages need
gd++ checkin --spec 4.7.2-stable # commit a dependency with the project
gd++ vendor --spec my-4.7 --from my-4.7 # add a custom one, e.g. from your own Godot build
gd++ build # build the packages in the current directory, for this machine, in debug mode
gd++ build res://... # build every package of the project
gd++ build --ship --for l.x64 w.x64 # release builds for Linux and Windows
gd++ test # build them, and run their tests in a headless Godot
gd++ clean # delete their build caches
gd++ ls # an overview of the project
gd++ trans player.gd++ # print the C++ that GD++ generates from a file
gd++ doc TypedArray # show what godot-cpp declares under a name
gd++ cat player.gd++ # show a file, highlighted
gd++ fix # tidy up the projectThe build writes the libraries and a .gdextension file into the package root, so Godot loads them right away.
A package can also hold plain C++ classes, written the usual godot-cpp way. gd++ init . --class Foo --include pkg://foo.h registers them with Godot. Add --ptr, or --ref for refcounted classes, to let GD++ code use them by name.
GD++ is ready to be used, but it's still experimental, and comes with absolutely no warranty. Syntax versions are designed for backward compatibility, but no guarantees can be given yet.
| Syntax | Status |
|---|---|
| 0 | Nightly: the language as it's being developed. Never use it in production. |
| 1 | Stable in theory, but experimental in practice. |
Each package chooses its syntax version in its .gd++pkg.
- Foliage3D: a realistic project by the same author, written fully in GD++, which shows what GD++ can do.
- gdpp-vim: Vim bindings for GD++.
- Godot Object Compiler: a similar project, which generates the boilerplate of GDExtensions from macros in plain C++ code.
GD++ is licensed under the MIT License.
GD++ was created by caphindsight. If GD++ helps you make a game, a mention in its credits would be very much appreciated. The MIT License doesn't require it.
