- Extending Godot Physics
- How the Physics Server works with Godot Nodes
- Rapier Physics Server Serialization
- Rapier Physics Server Fluids
- How to build
- How to debug
Godot let's any GDExtension create a new Physics Server
if they call register_server
on the PhysicsServer2DManager or PhysicsServer3DManager and on the callback return a new instance of their custom Physics Server
that extends either PhysicsServer2DExtension or PhysicsServer3DExtension.
A physics server has to implement 3 classes:
- PhysicsServer2DExtension or PhysicsServer3DExtension
- PhysicsDirectBodyState2DExtension or PhysicsDirectBodyState3DExtension
- PhysicsDirectSpaceState2DExtension or PhysicsDirectSpaceState3DExtension
Note that these functions all have underscore in begining of function name. The flow for how Godot calls them is the function without underscore calls into th one with underscore, eg.:
body_create()
|
v
_body_create()
Godot can register multiple Physics Servers
, and can decide at runtime which one to use.
Godot Rapier Physics implements these under the name like this:
- RapierPhysicsServer2D and RapierPhysicsServer3D
- RapierDirectBodyState2D and RapierDirectBodyState3D
- RapierDirectSpaceState2D and RapierDirectSpaceState3D
Code is reused as much as possible, by having each of these classes call into a generic class that does the implementation, and a few configuration flags to select dimensions, precision, etc.
The code written here is based on the Physics Server from Godot.
The Physics Server
is a singleton with a set of API's for bodies, areas, shapes and spaces. An example of this is body_create function. This function creates a body, and returns an RID. These RID
's are resource id's for objects that are handled by the Physics Server
.
Normally you wouldn't call these functions directly, but instead you would create a node that would call these functions. Eg. when you create a RigidBody2D
node, this calls the following:
body_rid = body_create()
body_set_space(body_rid, space_rid)
body_set_state(body_rid, BODY_STATE_TRANSFORM, Transform2D())
...
Also, aside from communication from Godot -> Physics Server
, there is also the reverse, where the Physics Server
notifies Godot of updates (eg. collision events, etc.). For this, Godot first calls into the Physics Server
's method, eg.:
These functions send a Callable
to the Physics Server
that it uses to call back into Godot and notify of certain changes.
The Rapier Physics Server
, which is our custom implementation of Physics Server
, hands out RID
's for objects it has internally, similar to how Godot Physics Server
does. The classes are named similar to how Godot naming works, but with Rapier instead of Godot, eg.:
RapierArea
RapierBody
RapierCollisionObjectBase
- ...
The difference from Godot Physics Server
is that resources are not using pointers, and as such are safe to be serialized.
However, there are some things that need to be reconstructed after saving and loading the state, namely:
Callable
RID
instance_id
canvas_instance_id
As described in the chapter above, the Physics Server
creates some resources and gives Godot RID
's that can be used to access them. Godot also gives some resources to the Physics Server
, eg. Callable
, that are used to notify Godot of updates (eg. collision events, etc.). Godot also gives to objects from Physics Server
instance_id's and canvas_instance_id's in order to identify a node corresponds to a resource.
As such, when saving and loading, first one must recreate the Godot scene and make sure all the dependencies are created, and only later load the Physics Server
state. Even if some of the things the Physics Server loads won't be the exact same, eg. RID
's, Callable
, etc. The simulation will work deterministic as internally it uses Rapier which is itself deterministic. Also the update order isn't based on these resources that Godot hands over.
Godot Rapier Physics also exposes new nodes, Fluid2D and Fluid3D. These nodes can set and get position, velocity and acceleration of particles used for fluid simulation. Internally it uses salva to create them.
- Prerequisites:
- Update dependencies to latest:
cargo update
- Build the project
# for 2d
cargo build --release --features="build2d" --no-default-features
# for 3d
cargo build --release --features="build3d" --no-default-features
- Copy the output to bin folder of the addon:
Eg. macOS
cp target/release/libgodot_rapier.dylib bin2d/addons/godot-rapier2d/bin/libgodot_rapier.macos.framework/libgodot_rapier.macos.dylib
Eg. Windows
cp target/release/godot_rapier.dll bin2d/addons/godot-rapier2d/bin/godot_rapier.windows.x86_64-pc-windows-msvc.dll
For the correct path to use inside the bin folder, look inside the bin2d/addons/godot-rapier2d.gdextension
or the bin3d/addons/godot-rapier3d.gdextension
.
For features, the following are available:
single-dim2
single-dim3
double-dim2
double-dim3
parallel
simd-stable
enhanced-determinism
serde-serialize
The single
and double
refer to the precision used in Godot.
The dim2
or dim3
refers to the rapier and salva versions used, and to what classes will be implemented for Godot and what Physics Server will be replaced(2d or 3d).
The parallel
version doesn't work on web.
The enhanced-determinism
usually slows down the simulation.
The serde-serialize
feature enabled serialization methods for physics server.
Click Run and Debug
in VSCode on the left. Add a configuration to the launch.configurations
similar to this (eg. below one is for macOS):
{
"name": "Launch",
"program": "path/to/godot/bin/godot.macos.editor.dev.arm64",
"type": "cppdbg",
"request": "launch",
"cwd": "${workspaceFolder:godot-rapier-2d}",
"osx": {
"MIMode": "lldb"
},
"args": [
"--path",
"path/to/project/folder",
"--debug-collisions",
"scene-name.tscn"
]
},
More on godot cli usage here.