Skip to content

rapier

stable

3D rigid-body physics simulation powered by rapier3d, exposing a PhysicsWorld with rigid bodies, colliders, joints, raycasting, and per-body force/impulse control.

use plugin rapier::{Physics3D.world, step, set_gravity, …}
39 functions Game
/ filter jk navigate Esc clear
Functions (39)
  1. Physics3D.world Create a new 3D physics world
  2. step Advance the simulation by one timestep
  3. set_gravity Set world gravity vector
  4. gravity Get current gravity vector
  5. set_timestep Set simulation timestep in seconds
  6. timestep Get current timestep
  7. raycast Cast a ray and return first hit
  8. create_rigid_body Add a rigid body to the world
  9. create_collider Attach a collider to a body
  10. create_joint Connect two bodies with a joint
  11. remove_joint Remove a joint from the world
  12. body_count Count rigid bodies in the world
  13. collider_count Count colliders in the world
  14. body_position Get body translation vector
  15. body_set_position Teleport a body to a position
  16. body_rotation Get body rotation quaternion
  17. body_linear_velocity Get body linear velocity vector
  18. body_set_linear_velocity Set body linear velocity
  19. body_apply_force Apply a continuous force to a body
  20. body_apply_impulse Apply an instant impulse to a body
  21. body_angular_velocity Get body angular velocity vector
  22. body_set_angular_velocity Set body angular velocity
  23. body_apply_torque Apply a continuous torque to a body
  24. body_apply_torque_impulse Apply an instant torque impulse
  25. body_mass Get body mass
  26. body_is_sleeping Check if body is sleeping
  27. body_wake_up Wake a sleeping body
  28. body_set_enabled Enable or disable a body
  29. body_is_enabled Check if body is enabled
  30. body_remove Remove a body from the world
  31. collider_set_restitution Set collider bounciness
  32. collider_restitution Get collider restitution
  33. collider_set_friction Set collider friction
  34. collider_friction Get collider friction
  35. collider_set_sensor Mark collider as sensor (no forces)
  36. collider_is_sensor Check if collider is a sensor
  37. collider_set_density Set collider density
  38. collider_remove Remove a collider from the world
  39. close Destroy the physics world

Overview

rapier wraps the rapier3d engine to give you a stateful 3D physics simulation. Everything lives inside a PhysicsWorld resource that you create with Physics3D.world; the world owns the rigid bodies, colliders, and joints, and it advances in discrete steps. Rigid bodies and colliders are referenced by integer handles returned at creation time, and every body/collider operation is a method on the world that takes the relevant handle as its first argument.

The typical loop is: build a world, add fixed and dynamic bodies, attach collider shapes to them, then call step() once per frame to integrate motion under gravity. Between steps you can read state (positions, velocities, mass, sleep status), push the simulation around with forces, impulses, torques, and velocity setters, query the scene with raycast, and tear things down with the *_remove and close helpers. Use it for games, simulations, or any scene that needs believable collisions, stacking, and constraints.

Common patterns

Drop a ball onto a floor and watch it fall over several steps:

use plugin rapier::{Physics3D}

let world = Physics3D.world()

let floor = world.create_rigid_body(#{"type": "fixed", "position": #{"x": 0.0, "y": 0.0, "z": 0.0}})
world.create_collider(floor, #{"shape": #{"type": "cuboid", "hx": 5.0, "hy": 0.1, "hz": 5.0}})

let ball = world.create_rigid_body(#{"type": "dynamic", "position": #{"x": 0.0, "y": 5.0, "z": 0.0}})
let ball_col = world.create_collider(ball, #{"shape": #{"type": "ball", "radius": 0.5}})
world.collider_set_restitution(ball_col, 0.7)

for i in 0..60 {
  world.step()
}
let pos = world.body_position(ball)
print("ball rested at y = {pos["y"]}")
world.close()

Launch a body with an impulse, then drive it with continuous force and torque:

use plugin rapier::{Physics3D}

let world = Physics3D.world()
let body = world.create_rigid_body(#{"type": "dynamic", "position": #{"x": 0.0, "y": 1.0, "z": 0.0}})
world.create_collider(body, #{"shape": #{"type": "ball", "radius": 0.5}})

world.body_apply_impulse(body, 0.0, 5.0, 0.0)
world.body_apply_force(body, 2.0, 0.0, 0.0)
world.body_apply_torque(body, 0.0, 1.0, 0.0)
world.step()

let vel = world.body_linear_velocity(body)
print("moving x = {vel["x"]}, y = {vel["y"]}")
world.close()

Cast a ray downward to find the ground beneath a point:

use plugin rapier::{Physics3D}

let world = Physics3D.world()
let floor = world.create_rigid_body(#{"type": "fixed", "position": #{"x": 0.0, "y": 0.0, "z": 0.0}})
world.create_collider(floor, #{"shape": #{"type": "cuboid", "hx": 10.0, "hy": 0.1, "hz": 10.0}})

let hit = world.raycast(#{
  "origin":    #{"x": 0.0, "y": 10.0, "z": 0.0},
  "direction": #{"x": 0.0, "y": -1.0, "z": 0.0},
  "max_distance": 100.0
})
if hit != nil {
  print("ground at distance {hit["distance"]}")
}
world.close()

Create a new 3D physics world

Creates a new physics world. config is an optional table with gravity: #{x, y, z} and dt: float. Defaults to Earth gravity (0, -9.81, 0) and a standard timestep.

use plugin rapier::{Physics3D}

let world = Physics3D.world()
let custom = Physics3D.world(#{"gravity": #{"x": 0.0, "y": -1.62, "z": 0.0}, "dt": 0.016})

Advance the simulation by one timestep

Advances the simulation by one timestep. Call this once per frame.

world.step()

Run several steps in a loop to integrate motion over time:

for i in 0..120 {
  world.step()
}

Set world gravity vector

Sets the gravity acceleration vector for the world.

world.set_gravity(0.0, -9.81, 0.0)   // Earth
world.set_gravity(0.0, -1.62, 0.0)   // Moon

Get current gravity vector

Returns the current gravity as #{x, y, z}.

let g = world.gravity()
print("gravity y: {g["y"]}")

Set simulation timestep in seconds

Sets the simulation timestep in seconds. Smaller values give higher accuracy but require more step() calls per second.

world.set_timestep(0.016)  // ~60 Hz

Get current timestep

Returns the current timestep in seconds.

print(world.timestep())

Cast a ray and return first hit

Casts a ray and returns the first hit as #{distance, point: #{x,y,z}}, or nil if nothing is hit. Config fields: origin: #{x,y,z}, direction: #{x,y,z}, max_distance: float, exclude_body: int.

let hit = world.raycast(#{
  "origin":    #{"x": 0.0, "y": 10.0, "z": 0.0},
  "direction": #{"x": 0.0, "y": -1.0, "z": 0.0},
  "max_distance": 100.0
})
if hit != nil {
  print("hit at distance {hit["distance"]}")
}

Use exclude_body to ignore the body firing the ray (useful for self-casts):

let hit = world.raycast(#{
  "origin":    #{"x": 0.0, "y": 2.0, "z": 0.0},
  "direction": #{"x": 0.0, "y": -1.0, "z": 0.0},
  "max_distance": 50.0,
  "exclude_body": player
})

Add a rigid body to the world

Adds a rigid body and returns an integer handle. Config fields: type ("dynamic", "fixed", "kinematic_position", "kinematic_velocity"), position: #{x,y,z}, locked_rotations: bool, linear_damping: float, ccd: bool.

let floor = world.create_rigid_body(#{"type": "fixed", "position": #{"x": 0.0, "y": 0.0, "z": 0.0}})
let ball  = world.create_rigid_body(#{"type": "dynamic", "position": #{"x": 0.0, "y": 5.0, "z": 0.0}})

Enable continuous collision detection and lock rotations for a fast projectile:

let bullet = world.create_rigid_body(#{
  "type": "dynamic",
  "position": #{"x": 0.0, "y": 1.0, "z": 0.0},
  "ccd": true,
  "locked_rotations": true,
  "linear_damping": 0.1
})

Attach a collider to a body

Attaches a collider to a body and returns a collider handle. Config has a shape table with type ("ball", "cuboid", "capsule"), plus shape-specific fields (radius, hx/hy/hz, half_height).

let ball_col = world.create_collider(ball, #{"shape": #{"type": "ball", "radius": 0.5}})
let box_col  = world.create_collider(floor, #{"shape": #{"type": "cuboid", "hx": 5.0, "hy": 0.1, "hz": 5.0}})

Capsules take both a half_height and a radius (handy for characters):

let player_col = world.create_collider(player, #{"shape": #{"type": "capsule", "half_height": 0.9, "radius": 0.4}})

Connect two bodies with a joint

Connects two bodies with a joint. Config type is "fixed", "revolute", "spherical", or "prismatic". Returns a joint handle. Fixed and spherical joints accept anchor1/anchor2 (#{x,y,z}); revolute and prismatic accept an axis (#{x,y,z}).

let j = world.create_joint(body_a, body_b, #{
  "type": "revolute",
  "axis": #{"x": 0.0, "y": 1.0, "z": 0.0}
})

A fixed joint rigidly welds two bodies at their local anchors:

let weld = world.create_joint(arm, hand, #{
  "type": "fixed",
  "anchor1": #{"x": 0.0, "y": -0.5, "z": 0.0},
  "anchor2": #{"x": 0.0, "y": 0.5, "z": 0.0}
})

Remove a joint from the world

Removes a joint from the simulation by its integer handle.

world.remove_joint(j)

Count rigid bodies in the world

Returns the total number of rigid bodies in the world.

print("bodies: {world.body_count()}")

Count colliders in the world

Returns the total number of colliders in the world.

print("colliders: {world.collider_count()}")

Get body translation vector

Returns the body translation as #{x, y, z}.

let pos = world.body_position(ball)
print("ball y: {pos["y"]}")

Teleport a body to a position

Teleports a body to a position, waking it if sleeping.

world.body_set_position(ball, 0.0, 5.0, 0.0)

Get body rotation quaternion

Returns the body orientation as a quaternion #{x, y, z, w}.

let rot = world.body_rotation(ball)
print("rot w: {rot["w"]}")

Get body linear velocity vector

Returns the linear velocity as #{x, y, z}.

let vel = world.body_linear_velocity(ball)
print("speed y: {vel["y"]}")

Set body linear velocity

Sets the body's linear velocity directly.

world.body_set_linear_velocity(ball, 0.0, 10.0, 0.0)

Apply a continuous force to a body

Applies a continuous force (in world space) to the body's center of mass. Accumulates until the next step().

world.body_apply_force(ball, 0.0, 100.0, 0.0)

Apply an instant impulse to a body

Applies an instant change in momentum to the body.

world.body_apply_impulse(ball, 0.0, 5.0, 0.0)

Get body angular velocity vector

Returns the body's angular velocity as #{x, y, z} (radians per second about each axis).

let spin = world.body_angular_velocity(ball)
print("yaw rate: {spin["y"]}")

Set body angular velocity

Sets the body's angular velocity directly, waking it if asleep.

world.body_set_angular_velocity(top, 0.0, 20.0, 0.0)

Apply a continuous torque to a body

Applies a continuous torque (rotational force) to the body. Accumulates until the next step().

world.body_apply_torque(ball, 0.0, 1.0, 0.0)

Apply an instant torque impulse

Applies an instant angular impulse, immediately changing the body's spin.

world.body_apply_torque_impulse(ball, 0.0, 5.0, 0.0)

Get body mass

Returns the body's total mass in kilograms (computed from collider density).

print("mass: {world.body_mass(ball)} kg")

Check if body is sleeping

Returns true if the body has come to rest and the engine has put it to sleep.

if world.body_is_sleeping(ball) {
  print("ball is at rest")
}

Wake a sleeping body

Forces a sleeping body back to the active simulation.

world.body_wake_up(ball)

Enable or disable a body

Enables or disables a body. A disabled body is removed from the simulation until re-enabled. Defaults to true when no value is given.

world.body_set_enabled(ball, false)  // freeze it
world.body_set_enabled(ball, true)   // bring it back

Check if body is enabled

Returns true if the body is currently participating in the simulation.

if !world.body_is_enabled(ball) {
  world.body_set_enabled(ball, true)
}

Remove a body from the world

Removes a rigid body and all its attached colliders from the world.

world.body_remove(ball)

Set collider bounciness

Sets the bounciness coefficient (0.0 = no bounce, 1.0 = perfectly elastic).

world.collider_set_restitution(ball_col, 0.8)

Get collider restitution

Returns the collider's current restitution (bounciness) coefficient.

print("bounce: {world.collider_restitution(ball_col)}")

Set collider friction

Sets the friction coefficient for the collider surface.

world.collider_set_friction(ball_col, 0.5)

Get collider friction

Returns the collider's current friction coefficient.

print("friction: {world.collider_friction(ball_col)}")

Mark collider as sensor (no forces)

Marks the collider as a sensor: it detects overlaps but does not generate contact forces.

world.collider_set_sensor(trigger_col, true)

Check if collider is a sensor

Returns true if the collider is configured as a sensor.

if world.collider_is_sensor(trigger_col) {
  print("this is a trigger volume")
}

Set collider density

Sets the density, which affects the parent body's mass.

world.collider_set_density(ball_col, 2.0)

Remove a collider from the world

Removes a collider from the world.

world.collider_remove(ball_col)

Destroy the physics world

Destroys the physics world and releases its resources.

world.close()
enespt-br