godot-rust/gdext
repository·master·Indexed 26 days ago
https://github.com/godot-rust/gdextRust bindings for Godot 4 (version 0.5.4) using the GDExtension API. It provides a type-safe, high-performance alternative to GDScript for games, editor plugins, and Godot-based applications. Key features include the #[derive(GodotClass)] attribute for defining Godot classes in Rust, support for virtual methods via traits, and thread-safe object access using GdCellBlocking.
What's inside godot-rust/gdext
- godot-rust is a library designed to integrate the Rust language with Godot 4 using the GDExtension API. It serves as a high-performance, type-safe alternative to GDScript. You can mix Rust and GDScript in the same project, allowing custom Rust APIs to be called type-safely from GDScript. The library is suitable for games, editor plugins, and other Godot-based applications.
Getting started with godot-rust
masterTo begin using godot-rust, refer to the following resources:
- The godot-rust Book: The primary guide for learning the library.
- API Docs: Detailed technical documentation for all exposed APIs.
- Demo Projects: Practical examples and small games to study implementation patterns.
If you encounter issues, you can join the community Discord and ask questions in the
#helpchannel.Define a Godot class in Rust
masterTo create a Godot class, use the
#[derive(GodotClass)]attribute on a struct. You can specify inheritance using the#[class(base=BaseClassName)]attribute and enable automatic initialization with#[class(init)].Key features include:
- Inheritance: Access base class methods via a
base: Base<BaseClassName>field. - Field Initialization: Use
#[init(val = value)]to set default values for fields. - Node Access: Use
#[init(node = "path/to/node")]with anOnReady<Gd<T>>type to automatically fetch a child node when_ready()is called. - Virtual Methods: Implement Godot's virtual methods by implementing the corresponding trait (e.g.,
ISprite2D) and marking the implementation with#[godot_api]. - Exposing Methods to GDScript: Use the
#[func]attribute on methods within an#[godot_api]implementation block to make them callable from GDScript.
use godot::classes::{ISprite2D, ProgressBar, Sprite2D}; use godot::prelude::*; // Declare the Player class inheriting Sprite2D. #[derive(GodotClass)] #[class(init, base=Sprite2D)] struct Player { base: Base<Sprite2D>, #[init(val = 100)] hitpoints: i32, #[init(node = "Ui/HealthBar")] health_bar: OnReady<Gd<ProgressBar>>, } #[godot_api] impl ISprite2D for Player { fn ready(&mut self) { godot_print!("Player ready!"); self.health_bar.set_max(self.hitpoints as f64); self.health_bar.set_value(self.hitpoints as f64); self.health_bar.signals().value_changed().connect(|hp| { godot_print!("Health changed to: {hp}"); }); } } #[godot_api] impl Player { #[func] fn take_damage(&mut self, damage: i32) { self.hitpoints -= damage; godot_print!("Player hit! HP left: {}", self.hitpoints); self.health_bar.set_value(self.hitpoints as f64); if self.hitpoints <= 0 { self.base_mut().queue_free(); } } }- Inheritance: Access base class methods via a
Use the `godot` crate instead of `godot-bindings`
masterThegodot-bindingscrate is an internal crate of godot-rust. Do not depend on this crate directly. Instead, use thegodotcrate for your development. No SemVer or other guarantees are provided forgodot-bindings.Use GDExtension libraries as dependencies
masterIf your crate depends on other GDExtension libraries, you must specify the main extension implementor using the
GDRUST_MAIN_EXTENSIONenvironment variable during build. This ensures all classes are loaded and callbacks are managed correctly.Example build command:
GDRUST_MAIN_EXTENSION="MyExtension" cargo buildRequirements for dependencies:
- Dependencies must be compilable as
rlib. In theirCargo.toml, they should havecrate-type = ["cdylib", "rlib"]or no[lib]section at all. - The name of the
ExtensionLibraryimplementor must be unique across your workspace and its dependencies.
- Dependencies must be compilable as
Use the `godot` crate instead of `godot-core`
masterThegodot-corecrate is an internal crate used by thegdextlibrary. It does not provide SemVer or other stability guarantees. End-users should depend on thegodotcrate for all development to ensure API stability and access to the intended public surface.Define Godot class properties with `#[var]` and `#[export]`
masterWhen defining a Godot class using
#[derive(GodotClass)], you can expose struct fields to the Godot engine using the#[var]and#[export]attributes.#[var]: Registers a field as a Godot property. You can specify custom getters, setters, renaming, and property hints.#[export]: A shorthand that automatically registers a field as an exported property in the Godot Inspector. If used without#[var], it infers the necessary property registration.
Properties can be organized into groups and subgroups using the group/subgroup metadata provided by the attributes.
Implement the ExtensionLibrary trait
masterEvery GDExtension Rust library must implement the
ExtensionLibrarytrait. This trait serves as the entry point for your extension, handling initialization, deinitialization, and lifecycle hooks. You must use the#[gdextension]proc-macro attribute on your implementation.Basic Usage
By default,
gdextautomatically registers all classes marked with#[derive(GodotClass)]and handles necessary setup.use godot::init::*; struct MyExtension; #[gdextension] unsafe impl ExtensionLibrary for MyExtension {}Custom Entry Symbol
If your
.gdextensionfile specifies a customentry_symbolin the[configuration]section, you must specify it in the attribute:#[gdextension(entry_symbol = custom_name)] unsafe impl ExtensionLibrary for MyExtension {}Use the godot::prelude for common imports
masterTo simplify your imports, you can use the prelude which contains frequently used symbols:
use godot::prelude::*;Configure RPC methods with the `#[rpc]` attribute
masterYou can define Godot Remote Procedure Call (RPC) methods in Rust using the
#[rpc]attribute. This attribute allows you to specify how the method is called across the network.There are two ways to configure an RPC:
1. Using Separated Arguments
You can pass individual configuration parameters directly into the attribute:
#[rpc(rpc_mode, transfer_mode, call_local, channel = N)]rpc_mode: UseRpcMode::AnyPeerorRpcMode::Authority.transfer_mode: UseTransferMode::Reliable,TransferMode::Unreliable, orTransferMode::UnreliableOrdered.call_local: A boolean indicating if the method should be called on the local instance.channel: Au32specifying the network channel.
2. Using a Configuration Expression
You can pass a pre-defined
RpcConfigobject using theconfigkey:#[rpc(config = RPC_CFG)]Configure custom Godot API via Cargo features
masterYou can control how the extension API and GDExtension interface are loaded by enabling specific Cargo features in your
Cargo.toml:api-custom: Regenerates all files by locating the Godot executable and reading its version and JSON files.api-custom-json: Generates files based on user-provided JSON files.
When using these features, the following functions become available to load the necessary metadata:
load_extension_api_json(watch: &mut StopWatch) -> Cow<'static, str>load_gdextension_interface_json(watch: &mut StopWatch) -> Cow<'static, str>
Enable WebAssembly (Wasm) support
masterTo target WebAssembly, you must explicitly opt-in using the
experimental-wasmfeature.- With Threads (Default): Requires the
wasm32-unknown-unknowntarget to be compiled with"-C", "link-args=-pthread". This must match Godot's Web export threading settings. - Without Threads: Enable the
experimental-wasm-nothreadsfeature (which requiresexperimental-wasm). This must be kept in sync with Godot's Web export setting (threading disabled) and should not use the-pthreadlink argument.
- With Threads (Default): Requires the