From 96418038581c3cb484aca93a42c606ebd17f6592 Mon Sep 17 00:00:00 2001 From: Jondolf Date: Sat, 17 Jun 2023 13:52:31 +0300 Subject: [PATCH] Add `Sensor` component for colliders --- src/components/collider.rs | 5 +++++ src/plugins/solver.rs | 16 ++++++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/components/collider.rs b/src/components/collider.rs index d118cd46..abadf927 100644 --- a/src/components/collider.rs +++ b/src/components/collider.rs @@ -246,6 +246,11 @@ fn extract_mesh_vertices_indices(mesh: &Mesh) -> Option { Some((vtx, idx)) } +/// Marks a [`Collider`] as a sensor collider. Sensor colliders send collision events but +/// don't cause a collision response. This is often used to detect when something enters or leaves an area. +#[derive(Reflect, Clone, Component, Debug, Default, PartialEq, Eq)] +pub struct Sensor; + /// The Axis-Aligned Bounding Box of a collider. #[derive(Clone, Copy, Component, Deref, DerefMut, PartialEq)] pub struct ColliderAabb(pub Aabb); diff --git a/src/plugins/solver.rs b/src/plugins/solver.rs index 798b855f..4aa147ef 100644 --- a/src/plugins/solver.rs +++ b/src/plugins/solver.rs @@ -85,6 +85,7 @@ fn penetration_constraints( mut bodies: Query<( RigidBodyQuery, &Collider, + Option<&Sensor>, Option<&CollisionLayers>, Option<&mut CollidingEntities>, Option<&Sleeping>, @@ -104,8 +105,8 @@ fn penetration_constraints( for (ent1, ent2) in broad_collision_pairs.0.iter() { if let Ok([bundle1, bundle2]) = bodies.get_many_mut([*ent1, *ent2]) { - let (mut body1, collider1, layers1, colliding_entities1, sleeping1) = bundle1; - let (mut body2, collider2, layers2, colliding_entities2, sleeping2) = bundle2; + let (mut body1, collider1, sensor1, layers1, colliding_entities1, sleeping1) = bundle1; + let (mut body2, collider2, sensor2, layers2, colliding_entities2, sleeping2) = bundle2; let layers1 = layers1.map_or(CollisionLayers::default(), |l| *l); let layers2 = layers2.map_or(CollisionLayers::default(), |l| *l); @@ -152,16 +153,19 @@ fn penetration_constraints( started_collisions.push(CollisionStarted(*ent1, *ent2)); } - // When an active body collides with a sleeping body, wake up the sleeping body. + // When an active body collides with a sleeping body, wake up the sleeping body if sleeping1.is_some() { commands.entity(*ent1).remove::(); } else if sleeping2.is_some() { commands.entity(*ent2).remove::(); } - let mut constraint = PenetrationConstraint::new(*ent1, *ent2, contact); - constraint.solve([&mut body1, &mut body2], sub_dt.0); - penetration_constraints.0.push(constraint); + // Create and solve constraint if both colliders are solid + if sensor1.is_none() && sensor2.is_none() { + let mut constraint = PenetrationConstraint::new(*ent1, *ent2, contact); + constraint.solve([&mut body1, &mut body2], sub_dt.0); + penetration_constraints.0.push(constraint); + } } else { let mut collision_ended_1 = false; let mut collision_ended_2 = false;