collider_creation_and_insertion
A collider is created by a ColliderBuilder structure that is based on the builder pattern. Then it needs
to be inserted into the physics world, i.e., into its ColliderSet,
which is processed by the physics-pipeline, collision-pipeline, and query-pipeline.
The following example shows several setters that can be called to customize the collider being built. The input values are just random so using this example as-is will not lead to a useful result.
- Example 2D
- Example 3D
use rapier2d::prelude::*;
use std::f32::consts::PI;
// The world that will contain our colliders.
let mut world = PhysicsWorld::new();
// Builder for a ball-shaped collider.
let _ = ColliderBuilder::ball(0.5);
// Builder for a cuboid-shaped collider.
let _ = ColliderBuilder::cuboid(0.5, 0.2);
// Builder for a capsule-shaped collider. The capsule principal axis is the `x` coordinate axis.
let _ = ColliderBuilder::capsule_x(0.5, 0.2);
// Builder for a capsule-shaped collider. The capsule principal axis is the `y` coordinate axis.
let _ = ColliderBuilder::capsule_y(0.5, 0.2);
// Builder for a triangle-mesh-shaped collider.
let _ = ColliderBuilder::trimesh(vertices, indices);
// Builder for a heightfield-shaped collider.
let _ = ColliderBuilder::heightfield(heights, scale);
// Builder for a collider with the given shape.
let collider = ColliderBuilder::new(SharedShape::ball(0.5))
// The collider translation wrt. the body it is attached to.
// Default: the zero vector.
.translation(Vector::new(1.0, 2.0))
// The collider rotation wrt. the body it is attached to.
// Default: the identity rotation.
.rotation(PI)
// The collider position wrt. the body it is attached to.
// Default: the identity isometry.
.position(Pose::new(Vector::new(1.0, 2.0), PI))
// The collider density. If non-zero the collider's mass and angular inertia will be added
// to the inertial properties of the body it is attached to.
// Default: 1.0
.density(1.3)
// The friction coefficient of this collider.
// Default: ColliderBuilder::default_friction() == 0.5
.friction(0.8)
// Whether this collider is a sensor.
// Default: false
.sensor(true)
// All done, actually build the collider.
.build();
// Insert the collider into the world, without attaching it to a rigid-body.
let collider_handle = world.insert_collider(collider.clone(), None);
let rigid_body_handle = world.insert_body(RigidBodyBuilder::dynamic().build());
// Or insert the collider into the world and attach it to a rigid-body.
let handle = world.insert_collider(collider, Some(rigid_body_handle));
use rapier3d::prelude::*;
use std::f32::consts::PI;
// The world that will contain our colliders.
let mut world = PhysicsWorld::new();
// Builder for a ball-shaped collider.
let _ = ColliderBuilder::ball(0.5);
// Builder for a cuboid-shaped collider.
let _ = ColliderBuilder::cuboid(0.5, 0.2, 0.1);
// Builder for a capsule-shaped collider. The capsule principal axis is the `x` coordinate axis.
let _ = ColliderBuilder::capsule_x(0.5, 0.2);
// Builder for a capsule-shaped collider. The capsule principal axis is the `y` coordinate axis.
let _ = ColliderBuilder::capsule_y(0.5, 0.2);
// Builder for a capsule-shaped collider. The capsule principal axis is the `z` coordinate axis.
let _ = ColliderBuilder::capsule_z(0.5, 0.2);
// Builder for a triangle-mesh-shaped collider.
let _ = ColliderBuilder::trimesh(vertices, indices);
// Builder for a heightfield-shaped collider.
let _ = ColliderBuilder::heightfield(heights, scale);
// Builder for a collider with the given shape.
let collider = ColliderBuilder::new(SharedShape::ball(0.5))
// The collider translation wrt. the body it is attached to.
// Default: the zero vector.
.translation(Vector::new(1.0, 2.0, 3.0))
// The collider rotation wrt. the body it is attached to.
// Default: the identity rotation.
.rotation(Vector::new(0.0, PI, 0.0))
// The collider position wrt. the body it is attached to.
// Default: the identity isometry.
.position(Pose::new(Vector::new(1.0, 2.0, 3.0), Vector::new(0.0, PI, 0.0)))
// The collider density. If non-zero the collider's mass and angular inertia will be added
// to the inertial properties of the body it is attached to.
// Default: 1.0
.density(1.3)
// The friction coefficient of this collider.
// Default: ColliderBuilder::default_friction() == 0.5
.friction(0.8)
// Whether this collider is a sensor.
// Default: false
.sensor(true)
// All done, actually build the collider.
.build();
// Insert the collider into the world, without attaching it to a rigid-body.
let handle = world.insert_collider(collider.clone(), None);
let rigid_body_handle = world.insert_body(RigidBodyBuilder::dynamic().build());
// Or insert the collider into the world and attach it to a rigid-body.
let handle = world.insert_collider(collider, Some(rigid_body_handle));
A collider is created by adding the Collider component. Other components like Transform,
Sensor, Friction, etc. can be added to customize the collider. Removing one of these optional components
afterwards resets the corresponding property of the collider to its default value.
The following example shows several initializations of components to customize collider being built. The input values are just random so using this example as-is will not lead to a useful result.
- Example 2D
- Example 3D
use bevy_rapier2d::prelude::*;
commands
.spawn(Collider::cuboid(1.0, 2.0))
.insert(Sensor)
.insert(Transform::from_xyz(2.0, 0.0, 0.0))
.insert(Friction::coefficient(0.7))
.insert(Restitution::coefficient(0.3))
.insert(ColliderMassProperties::Density(2.0));
use bevy_rapier3d::prelude::*;
commands
.spawn(Collider::cuboid(1.0, 2.0, 1.0))
.insert(Sensor)
.insert(Transform::from_xyz(2.0, 0.0, 0.0))
.insert(Friction::coefficient(0.7))
.insert(Restitution::coefficient(0.3))
.insert(ColliderMassProperties::Density(2.0));
A collider can optionally be attached to a rigid-body. Attaching a collider to a rigid-body will result in the rigid-body being affected by collisions. The collider's position will be automatically updated from the position of the rigid-body it is attached to. There are two ways of attaching a collider to a rigid-body. The second way allows you to attach multiple colliders to the same rigid-body:
- Attach the
Colliderto the same entity as theRigidBody. - Attach the
Colliderto an entity that is a child of the entity containing theRigidBody.
// Attach a single collider to a rigid-body.
commands
.spawn(RigidBody::Dynamic)
.insert(Collider::ball(0.5));
// Attach a multiple colliders to a rigid-body.
commands
.spawn((RigidBody::Dynamic, GlobalTransform::default()))
.with_children(|children| {
children
.spawn(Collider::ball(0.5))
// Position the collider relative to the rigid-body.
.insert(Transform::from_xyz(0.0, 0.0, -1.0));
children
.spawn(Collider::ball(0.5))
// Position the collider relative to the rigid-body.
.insert(Transform::from_xyz(0.0, 0.0, 1.0));
});
A collider is created by a World.createCollider method. The initial state of
the collider to create is described by an instance of the ColliderDesc class.
Each collider create by the physics world is given an integer identifier. This identifier
is guaranteed to the different from any identifier of colliders still existing in the physics
world. However, the identifier may be equal to the identifier of an older collider that has
already been removed from the physics world with World.removeCollider.
The following example shows several setters that can be called to customize the collider being built. The input values are just random so using this example as-is will not lead to a useful result.
- Example 2D
- Example 3D
// The physics world.
let world = new RAPIER.World({ x: 0.0, y: -9.81 });
// Builder for a ball-shaped collider.
let example1 = RAPIER.ColliderDesc.ball(0.5);
// Builder for a cuboid-shaped collider.
let example2 = RAPIER.ColliderDesc.cuboid(0.5, 0.2);
// Builder for a capsule-shaped collider. The capsule principal axis is the `y` coordinate axis.
let example3 = RAPIER.ColliderDesc.capsule(0.5, 0.2);
// Builder for a triangle-mesh-shaped collider.
let example4 = RAPIER.ColliderDesc.trimesh(vertices, indices);
// Builder for a heightfield-shaped collider.
let example5 = RAPIER.ColliderDesc.heightfield(heights, scale);
// Builder for a collider with the given shape.
let colliderDesc = new RAPIER.ColliderDesc(new RAPIER.Ball(0.5))
// The collider translation wrt. the body it is attached to.
// Default: the zero vector.
.setTranslation(1.0, 2.0)
// The collider rotation wrt. the body it is attached to.
// Default: the identity rotation.
.setRotation(3.14)
// The collider density. If non-zero the collider's mass and angular inertia will be added
// to the inertial properties of the body it is attached to.
// Default: 1.0
.setDensity(1.3)
// The friction coefficient of this collider.
// Default: 0.5
.setFriction(0.8)
// Whether this collider is a sensor.
// Default: false
.setSensor(true);
// Create the collider, without attaching it to a rigid-body.
let handle = world.createCollider(colliderDesc);
// Or create the collider and attach it to a rigid-body.
let rigidBody = world.createRigidBody(RAPIER.RigidBodyDesc.dynamic());
let collider = world.createCollider(colliderDesc, rigidBody);
// The physics world.
let world = new RAPIER.World({ x: 0.0, y: -9.81, z: 0.0 });
// Builder for a ball-shaped collider.
let example1 = RAPIER.ColliderDesc.ball(0.5);
// Builder for a cuboid-shaped collider.
let example2 = RAPIER.ColliderDesc.cuboid(0.5, 0.2, 0.1);
// Builder for a capsule-shaped collider. The capsule principal axis is the `y` coordinate axis.
let example3 = RAPIER.ColliderDesc.capsule(0.5, 0.2);
// Builder for a triangle-mesh-shaped collider.
let example4 = RAPIER.ColliderDesc.trimesh(vertices, indices);
// Builder for a heightfield-shaped collider.
let example5 = RAPIER.ColliderDesc.heightfield(2, 2, heights, scale);
// Builder for a collider with the given shape.
let colliderDesc = new RAPIER.ColliderDesc(new RAPIER.Ball(0.5))
// The collider translation wrt. the body it is attached to.
// Default: the zero vector.
.setTranslation(1.0, 2.0, 3.0)
// The collider rotation wrt. the body it is attached to, as a unit quaternion.
// Default: the identity rotation.
.setRotation({ w: 1.0, x: 0.0, y: 0.0, z: 0.0 })
// The collider density. If non-zero the collider's mass and angular inertia will be added
// to the inertial properties of the body it is attached to.
// Default: 1.0
.setDensity(1.3)
// The friction coefficient of this collider.
// Default: 0.5
.setFriction(0.8)
// Whether this collider is a sensor.
// Default: false
.setSensor(true);
// Create the collider, without attaching it to a rigid-body.
let handle = world.createCollider(colliderDesc);
// Or create the collider and attach it to a rigid-body.
let rigidBody = world.createRigidBody(RAPIER.RigidBodyDesc.dynamic());
let collider = world.createCollider(colliderDesc, rigidBody);
A collider is described by a R3ColliderDesc structure, initialized by one of its constructors (e.g.
r3BallColliderDesc, r3CuboidColliderDesc, r3CapsuleYColliderDesc, or r3DefaultColliderDesc) which set
meaningful default values to all its fields. Its geometric shape is given by its shape field, a R3ShapeDesc
whose kind (e.g. R3_SHAPE_DESC_CUBOID) selects which of its fields are actually read. Then it needs to be
inserted into the physics world: with r3InsertCollider to attach it
to a rigid-body, or with r3InsertColliderWithoutParent otherwise. Both return the R3ColliderHandle identifying
the new collider.
The arrays referenced by a description (vertex buffers, index buffers, compound children, etc.) are only borrowed
until its insertion returns: they can be freed or reused right after. This is also the case of the shared
shapes (R3SharedShape) a description can point to, with the R3_SHAPE_DESC_SHARED kind. A shared shape is an
immutable geometry created by one of the r3...SharedShape functions (e.g. r3BallSharedShape), which can be given
to any number of colliders, and must be freed with r3FreeSharedShape. Some shapes, like convex decompositions or
voxels, can only be created as shared shapes.
The following example shows several fields that can be set to customize the collider being described. The input values are just random so using this example as-is will not lead to a useful result.
- Example 2D
- Example 3D
// The world that will contain our colliders.
R2World *world = r2NewWorld();
// Description of a ball-shaped collider.
R2ColliderDesc ball = r2BallColliderDesc(0.5);
// Description of a cuboid-shaped collider.
R2ColliderDesc cuboid = r2CuboidColliderDesc(r2Vector(0.5, 0.2));
// Description of a capsule-shaped collider. The capsule principal axis is the `x` coordinate axis.
R2ColliderDesc capsule_x = r2CapsuleXColliderDesc(0.5, 0.2);
// Description of a capsule-shaped collider. The capsule principal axis is the `y` coordinate axis.
R2ColliderDesc capsule_y = r2CapsuleYColliderDesc(0.5, 0.2);
// Description of a triangle-mesh-shaped collider.
R2ColliderDesc trimesh = r2DefaultColliderDesc();
r2ShapeDesc_SetTrimesh(&trimesh.shape, (R2VectorView){vertices, 3}, (R2TriangleView){indices, 1}, 0);
// Description of a heightfield-shaped collider.
R2ColliderDesc heightfield = r2DefaultColliderDesc();
heightfield.shape.kind = R2_SHAPE_DESC_HEIGHTFIELD;
heightfield.shape.heights = (R2RealView){heights, 4};
heightfield.shape.rows = 4;
heightfield.shape.columns = 1;
heightfield.shape.scale = scale;
// Description of a collider with the given shared shape.
R2SharedShape *shape = r2BallSharedShape(0.5);
R2ColliderDesc collider = r2DefaultColliderDesc();
collider.shape.kind = R2_SHAPE_DESC_SHARED;
collider.shape.sharedShape = shape;
// The collider translation wrt. the body it is attached to.
// Default: the zero vector.
collider.position.translation = r2Vector(1.0, 2.0);
// The collider rotation wrt. the body it is attached to.
// Default: the identity rotation.
collider.position.rotation = r2Rotation(R2_PI);
// The collider position wrt. the body it is attached to.
// Default: the identity pose.
collider.position = r2Pose(r2Vector(1.0, 2.0), r2Rotation(R2_PI));
// The collider density. If non-zero the collider's mass and angular inertia will be added
// to the inertial properties of the body it is attached to.
// Default: 1.0
collider.density = 1.3;
// The friction coefficient of this collider.
// Default: 0.5
collider.friction = 0.8;
// Whether this collider is a sensor.
// Default: 0
collider.isSensor = 1;
// Insert the collider into the world, without attaching it to a rigid-body.
R2ColliderHandle collider_handle = r2InsertColliderWithoutParent(world, &collider);
R2RigidBodyDesc rigid_body = r2DynamicRigidBodyDesc();
R2RigidBodyHandle rigid_body_handle = r2InsertRigidBody(world, &rigid_body);
// Or insert the collider into the world and attach it to a rigid-body.
R2ColliderHandle handle = r2InsertCollider(rigid_body_handle, &collider);
// The descriptions only borrow the shared shape: free it once it is no longer needed.
r2FreeSharedShape(shape);
// The world that will contain our colliders.
R3World *world = r3NewWorld();
// Description of a ball-shaped collider.
R3ColliderDesc ball = r3BallColliderDesc(0.5);
// Description of a cuboid-shaped collider.
R3ColliderDesc cuboid = r3CuboidColliderDesc(r3Vector(0.5, 0.2, 0.1));
// Description of a capsule-shaped collider. The capsule principal axis is the `x` coordinate axis.
R3ColliderDesc capsule_x = r3CapsuleXColliderDesc(0.5, 0.2);
// Description of a capsule-shaped collider. The capsule principal axis is the `y` coordinate axis.
R3ColliderDesc capsule_y = r3CapsuleYColliderDesc(0.5, 0.2);
// Description of a capsule-shaped collider. The capsule principal axis is the `z` coordinate axis.
R3ColliderDesc capsule_z = r3CapsuleZColliderDesc(0.5, 0.2);
// Description of a triangle-mesh-shaped collider.
R3ColliderDesc trimesh = r3DefaultColliderDesc();
r3ShapeDesc_SetTrimesh(&trimesh.shape, (R3VectorView){vertices, 3}, (R3TriangleView){indices, 1}, 0);
// Description of a heightfield-shaped collider (heights in column-major order).
R3ColliderDesc heightfield = r3DefaultColliderDesc();
heightfield.shape.kind = R3_SHAPE_DESC_HEIGHTFIELD;
heightfield.shape.heights = (R3RealView){heights, 4};
heightfield.shape.rows = 2;
heightfield.shape.columns = 2;
heightfield.shape.scale = scale;
// Description of a collider with the given shared shape.
R3SharedShape *shape = r3BallSharedShape(0.5);
R3ColliderDesc collider = r3DefaultColliderDesc();
collider.shape.kind = R3_SHAPE_DESC_SHARED;
collider.shape.sharedShape = shape;
// The collider translation wrt. the body it is attached to.
// Default: the zero vector.
collider.position.translation = r3Vector(1.0, 2.0, 3.0);
// The collider rotation wrt. the body it is attached to.
// Default: the identity rotation.
collider.position.rotation = r3RotationFromAxisAngle(r3Vector(0.0, 1.0, 0.0), R3_PI);
// The collider position wrt. the body it is attached to.
// Default: the identity pose.
collider.position = r3Pose(r3Vector(1.0, 2.0, 3.0), r3RotationFromAxisAngle(r3Vector(0.0, 1.0, 0.0), R3_PI));
// The collider density. If non-zero the collider's mass and angular inertia will be added
// to the inertial properties of the body it is attached to.
// Default: 1.0
collider.density = 1.3;
// The friction coefficient of this collider.
// Default: 0.5
collider.friction = 0.8;
// Whether this collider is a sensor.
// Default: 0
collider.isSensor = 1;
// Insert the collider into the world, without attaching it to a rigid-body.
R3ColliderHandle collider_handle = r3InsertColliderWithoutParent(world, &collider);
R3RigidBodyDesc rigid_body = r3DynamicRigidBodyDesc();
R3RigidBodyHandle rigid_body_handle = r3InsertRigidBody(world, &rigid_body);
// Or insert the collider into the world and attach it to a rigid-body.
R3ColliderHandle handle = r3InsertCollider(rigid_body_handle, &collider);
// The descriptions only borrow the shared shape: free it once it is no longer needed.
r3FreeSharedShape(shape);
A collider can also be disabled, by setting the enabled field of its description to 0 or, after its creation, with
r3Collider_SetEnabled. A disabled collider is excluded from all the collision-detection and physics until it is
enabled again, which is useful to "turn off" a collider temporarily without removing it (a collider is removed from
the world with r3RemoveCollider).
A collider is created by a ColliderBuilder that is based on the builder pattern: it is returned by one of the shape
constructors of the Collider class (e.g. Collider.ball, Collider.cuboid, or Collider.new which takes any
SharedShape), each of its methods returns a builder with the corresponding property set, and its build method
returns the Collider. These properties can also be given as keyword arguments of the shape constructors, e.g.,
Collider.ball(0.5, density=2.0, friction=0.3). Then it needs to be inserted into the physics world
with PhysicsWorld.add_collider, which attaches it to the rigid-body given as its optional parent argument, and
returns the ColliderHandle identifying the new collider. Colliders can also be inserted together with the rigid-body
they are attached to with the colliders argument of PhysicsWorld.add_body. Once inserted, the collider is accessed
with world.colliders[handle], which returns a live view: assigning one of its properties modifies the collider of
the physics world directly.
The following example shows several setters that can be called to customize the collider being built. The input values are just random so using this example as-is will not lead to a useful result.
import math
import rapier3d as rp
# The world that will contain our colliders.
world = rp.PhysicsWorld()
# Builder for a ball-shaped collider.
_ = rp.Collider.ball(0.5)
# Builder for a cuboid-shaped collider.
_ = rp.Collider.cuboid(0.5, 0.2, 0.1)
# Builder for a capsule-shaped collider. The capsule principal axis is the `x` coordinate axis.
_ = rp.Collider.capsule_x(0.5, 0.2)
# Builder for a capsule-shaped collider. The capsule principal axis is the `y` coordinate axis.
_ = rp.Collider.capsule_y(0.5, 0.2)
# Builder for a capsule-shaped collider. The capsule principal axis is the `z` coordinate axis.
_ = rp.Collider.capsule_z(0.5, 0.2)
# Builder for a triangle-mesh-shaped collider.
_ = rp.Collider.trimesh(vertices, indices)
# Builder for a heightfield-shaped collider.
_ = rp.Collider.heightfield(heights, scale)
# Builder for a collider with the given shape.
collider = (
rp.Collider.new(rp.SharedShape.ball(0.5))
# The collider translation wrt. the body it is attached to.
# Default: the zero vector.
.translation((1.0, 2.0, 3.0))
# The collider rotation wrt. the body it is attached to, as a rotation vector (axis * angle).
# Default: the identity rotation.
.rotation((0.0, math.pi, 0.0))
# The collider position wrt. the body it is attached to.
# Default: the identity isometry.
.position(rp.Isometry3((1.0, 2.0, 3.0), rp.Rotation3.from_scaled_axis((0.0, math.pi, 0.0))))
# The collider density. If non-zero the collider's mass and angular inertia will be added
# to the inertial properties of the body it is attached to.
# Default: 1.0
.density(1.3)
# The friction coefficient of this collider.
# Default: 0.5
.friction(0.8)
# Whether this collider is a sensor.
# Default: False
.sensor(True)
# All done, actually build the collider.
.build()
)
# Insert the collider into the world, without attaching it to a rigid-body.
collider_handle = world.add_collider(collider)
rigid_body_handle = world.add_body(rp.RigidBody.dynamic())
# Or insert the collider into the world and attach it to a rigid-body.
handle = world.add_collider(collider, parent=rigid_body_handle)
A collider can also be disabled, with ColliderBuilder.enabled(False) or, after its creation, by setting its
is_enabled property to False. A disabled collider is excluded from all the collision-detection and physics until
it is enabled again, which is useful to "turn off" a collider temporarily without removing it (a collider is removed
from the world with PhysicsWorld.remove_collider).