Colliders
Colliders define the physical shape of objects for collision detection.
Collider Shapes
Ball (Sphere)
#![allow(unused)] fn main() { world.core.set_collider(entity, ColliderComponent::new_ball(0.5)); }
Cuboid (Box)
#![allow(unused)] fn main() { world.core.set_collider(entity, ColliderComponent::new_cuboid(1.0, 0.5, 1.0)); }
Capsule
Perfect for characters:
#![allow(unused)] fn main() { world.core.set_collider(entity, ColliderComponent::new_capsule(1.0, 0.3)); }
Cylinder
#![allow(unused)] fn main() { world.core.set_collider(entity, ColliderComponent { shape: ColliderShape::Cylinder { half_height: 1.0, radius: 0.5, }, ..Default::default() }); }
Cone
#![allow(unused)] fn main() { world.core.set_collider(entity, ColliderComponent { shape: ColliderShape::Cone { half_height: 1.0, radius: 0.5, }, ..Default::default() }); }
Triangle Mesh
For complex static geometry:
#![allow(unused)] fn main() { let vertices: Vec<[f32; 3]> = mesh.vertices.iter() .map(|v| v.position) .collect(); let indices: Vec<[u32; 3]> = mesh.indices .chunks(3) .map(|c| [c[0], c[1], c[2]]) .collect(); world.core.set_collider(entity, ColliderComponent { shape: ColliderShape::TriMesh { vertices, indices }, ..Default::default() }); }
Heightfield
For terrain:
#![allow(unused)] fn main() { let heights: Vec<f32> = generate_height_grid(64, 64); world.core.set_collider(entity, ColliderComponent { shape: ColliderShape::HeightField { nrows: 64, ncols: 64, heights, scale: [100.0, 50.0, 100.0], }, ..Default::default() }); }
Compound
Multiple shapes combined:
#![allow(unused)] fn main() { let body_collider = ColliderComponent::new_cuboid(0.5, 0.1, 0.5); let head_collider = ColliderComponent::new_ball(0.3); }
Physics Materials
Friction, restitution, and density are fields directly on ColliderComponent:
#![allow(unused)] fn main() { world.core.set_collider(entity, ColliderComponent::new_cuboid(0.5, 0.5, 0.5) .with_friction(0.5) // Sliding resistance (0 = ice, 1 = rubber) .with_restitution(0.3) // Bounciness (0 = no bounce, 1 = perfect bounce) .with_density(1.0)); // Mass per unit volume }
Material Examples
#![allow(unused)] fn main() { // Ice let ice = ColliderComponent::new_cuboid(0.5, 0.5, 0.5) .with_friction(0.05) .with_restitution(0.1) .with_density(0.9); // Rubber let rubber = ColliderComponent::new_ball(0.5) .with_friction(0.9) .with_restitution(0.8) .with_density(1.1); // Metal let metal = ColliderComponent::new_cuboid(0.5, 0.5, 0.5) .with_friction(0.4) .with_restitution(0.2) .with_density(7.8); }
Collision Groups
Filter which objects collide:
#![allow(unused)] fn main() { use rapier3d::prelude::*; // Define groups const GROUP_PLAYER: Group = Group::GROUP_1; const GROUP_ENEMY: Group = Group::GROUP_2; const GROUP_PROJECTILE: Group = Group::GROUP_3; const GROUP_WORLD: Group = Group::GROUP_4; // Player collides with enemies and world, not own projectiles let player_filter = CollisionGroups::new( GROUP_PLAYER, GROUP_ENEMY | GROUP_WORLD, ); }
Sensor Colliders
Detect overlaps without physical response:
#![allow(unused)] fn main() { // Create a trigger zone if let Some(collider) = world.resources.physics.collider_set.get_mut(handle.into()) { collider.set_sensor(true); } }
Sensor collisions are reported through the collision events system (see below).
Collision Events
Query collision pairs each frame. collision_events() returns &[CollisionEvent]:
#![allow(unused)] fn main() { fn run_systems(&mut self, world: &mut World) { for event in world.resources.physics.collision_events() { match event.kind { CollisionEventKind::Started => { handle_collision_start(event.entity_a, event.entity_b); } CollisionEventKind::Stopped => { handle_collision_end(event.entity_a, event.entity_b); } } } } }
Each CollisionEvent has:
#![allow(unused)] fn main() { pub struct CollisionEvent { pub entity_a: Entity, pub entity_b: Entity, pub kind: CollisionEventKind, pub is_sensor: bool, } }
Convex Decomposition
For complex shapes on dynamic bodies, use convex decomposition:
#![allow(unused)] fn main() { use rapier3d::prelude::*; // This creates multiple convex pieces from a concave mesh let decomposed = SharedShape::convex_decomposition(&vertices, &indices); }
Performance Tips
| Shape | Performance | Use Case |
|---|---|---|
| Ball | Fastest | Rolling objects |
| Cuboid | Fast | Crates, buildings |
| Capsule | Fast | Characters |
| Cylinder | Medium | Barrels, pillars |
| Convex | Medium | Simple props |
| Trimesh | Slow | Static terrain only |
| Compound | Varies | Complex dynamic objects |
- Prefer primitive shapes over meshes
- Use trimesh only for static geometry
- Compound colliders are better than multiple entities
- Simplify collision geometry vs visual geometry