Attribute Macro godot_api
#[godot_api]
Expand description
Proc-macro attribute to be used with impl
blocks of #[derive(GodotClass)]
structs.
Can be used in two ways:
#[derive(GodotClass)]
#[class(init, base=Node)]
struct MyClass {}
// 1) inherent impl block: user-defined, custom API.
#[godot_api]
impl MyClass { /* ... */ }
// 2) trait impl block: implement Godot-specific APIs.
#[godot_api]
impl INode for MyClass { /* ... */ }
The second case works by implementing the corresponding trait I*
for the base class of your class
(for example IRefCounted
or INode3D
). Then, you can add functionality such as:
init
constructors- lifecycle methods like
ready
orprocess
on_notification
methodto_string
method
Neither of the two #[godot_api]
blocks is required. For small data bundles inheriting RefCounted
, you may be fine with
accessing properties directly from GDScript.
See also book chapter Registering functions and following.
Table of contents
- Constructors
- Lifecycle functions
- User-defined functions
- Constants and signals
- Multiple inherent
impl
blocks
§Constructors
Note that init
(the Godot default constructor) can be either provided by overriding it, or generated with a #[class(init)]
attribute
on the struct. Classes without init
cannot be instantiated from GDScript.
§User-defined init
#[derive(GodotClass)]
// no #[class(init)] here, since init() is overridden below.
// #[class(base=RefCounted)] is implied if no base is specified.
struct MyStruct;
#[godot_api]
impl IRefCounted for MyStruct {
fn init(_base: Base<RefCounted>) -> Self {
MyStruct
}
}
§Generated init
This initializes the Base<T>
field, and every other field with either Default::default()
or the value specified in #[init(val = ...)]
.
#[derive(GodotClass)]
#[class(init, base=Node)]
pub struct MyNode {
base: Base<Node>,
#[init(val = 42)]
some_integer: i64,
}
§Lifecycle functions
You can override the lifecycle functions ready
, process
, physics_process
and so on, by implementing the trait corresponding to the
base class.
#[derive(GodotClass)]
#[class(init, base=Node)]
pub struct MyNode;
#[godot_api]
impl INode for MyNode {
fn ready(&mut self) {
godot_print!("Hello World!");
}
}
Using any trait other than the one corresponding with the base class will result in compilation failure.
#[derive(GodotClass)]
#[class(init, base=Node3D)]
pub struct My3DNode;
#[godot_api]
impl INode for My3DNode {
fn ready(&mut self) {
godot_print!("Hello World!");
}
}
§User-defined functions
You can use the #[func]
attribute to declare your own functions. These are exposed to Godot and callable from GDScript.
§Associated functions and methods
If #[func]
functions are called from the engine, they implicitly bind the surrounding Gd<T>
pointer: Gd::bind()
in case of &self
,
Gd::bind_mut()
in case of &mut self
. To avoid that, use #[func(gd_self)]
, which requires an explicit first argument of type Gd<T>
.
Functions without a receiver become static functions in Godot. They can be called from GDScript using MyStruct.static_function()
.
If they return Gd<Self>
, they are effectively constructors that allow taking arguments.
#[derive(GodotClass)]
#[class(init)]
struct MyStruct {
field: i64,
base: Base<RefCounted>,
}
#[godot_api]
impl MyStruct {
#[func]
pub fn hello_world(&mut self) {
godot_print!("Hello World!")
}
#[func]
pub fn static_function(constructor_arg: i64) -> Gd<Self> {
Gd::from_init_fn(|base| {
MyStruct { field: constructor_arg, base }
})
}
#[func(gd_self)]
pub fn explicit_receiver(mut this: Gd<Self>, other_arg: bool) {
// Only bind Gd pointer if needed.
if other_arg {
this.bind_mut().field = 55;
}
}
}
§Virtual methods
Functions with the #[func(virtual)]
attribute are virtual functions, meaning attached scripts can override them.
#[derive(GodotClass)]
#[class(init)]
struct MyStruct {
// Virtual functions require base object.
base: Base<RefCounted>,
}
#[godot_api]
impl MyStruct {
#[func(virtual)]
fn language(&self) -> GString {
GString::from("Rust")
}
}
In GDScript, your method is available with a _
prefix, following Godot convention for virtual methods:
extends MyStruct
func _language():
return "GDScript"
Now, obj.language()
from Rust will dynamically dispatch the call.
Make sure you understand the limitations in the tutorial.
§RPC attributes
You can use the #[rpc]
attribute to let your functions act as remote procedure calls (RPCs) in Godot. This is the Rust equivalent of
GDScript’s @rpc
annotation.
#[rpc]
is only supported for classes inheriting Node
, and they need to declare a Base<T>
field.
The syntax follows GDScript’a @rpc
. You can optionally specify up to four keys; omitted ones use their default value.
Here’s an overview:
Setting | Type | Possible values (first is default) |
---|---|---|
RPC mode | RpcMode | authority , any_peer |
Sync | bool | call_remote , call_local |
Transfer mode | TransferMode | unreliable , unreliable_ordered , reliable |
Channel | u32 | any |
You can also use #[rpc(config = value)]
, with value
being an expression of type RpcConfig
in scope, for example a const
or the
call to a function. This can be useful to reuse configurations across multiple RPCs.
#[rpc]
implies #[func]
. You can use both attributes together, if you need to configure other #[func]
-specific keys.
For example, the following method declarations are all equivalent:
use godot::classes::multiplayer_api::RpcMode;
use godot::classes::multiplayer_peer::TransferMode;
use godot::prelude::*;
use godot::register::RpcConfig;
#[godot_api]
impl MyStruct {
#[rpc(unreliable_ordered, channel = 2)]
fn with_defaults(&mut self) {}
#[rpc(authority, unreliable_ordered, call_remote, channel = 2)]
fn explicit(&mut self) {}
#[rpc(config = MY_RPC_CONFIG)]
fn external_config_const(&mut self) {}
#[rpc(config = my_rpc_provider())]
fn external_config_fn(&mut self) {}
}
const MY_RPC_CONFIG: RpcConfig = RpcConfig {
rpc_mode: RpcMode::AUTHORITY,
transfer_mode: TransferMode::UNRELIABLE_ORDERED,
call_local: false,
channel: 2,
};
fn my_rpc_provider() -> RpcConfig {
RpcConfig {
transfer_mode: TransferMode::UNRELIABLE_ORDERED,
channel: 2,
..Default::default() // only possible in fn, not in const.
}
}
§Constants and signals
Please refer to the book.
§Multiple inherent impl
blocks
Just like with regular structs, you can have multiple inherent impl
blocks. This can be useful for code organization or when you want to generate code from a proc-macro.
For implementation reasons, all but one impl
blocks must have the key secondary
. There is no difference between implementing all functions in one block or splitting them up between multiple blocks.
#[godot_api]
impl MyStruct {
#[func]
pub fn one(&self) { }
}
#[godot_api(secondary)]
impl MyStruct {
#[func]
pub fn two(&self) { }
}