feat: Added detect_colliders system

- Fixed colliders filtering in check_for_collisions
- Fixed group masks in tests
- Test collider_detects_different_groups now passes
This commit is contained in:
Alexey 2026-02-15 14:15:00 +03:00
commit 8f667f08c6
2 changed files with 21 additions and 11 deletions

View file

@ -105,7 +105,6 @@ impl Collider {
/// Returns true if any of self shapes intersect other's shapes, respecting groups. /// Returns true if any of self shapes intersect other's shapes, respecting groups.
/// Wrapper around [intersects_unchecked](Self::intersects_unchecked) /// Wrapper around [intersects_unchecked](Self::intersects_unchecked)
pub fn intersects(&self, other: &Collider) -> bool { pub fn intersects(&self, other: &Collider) -> bool {
println!("groups: {}", self.check_mask & other.mask );
if self.check_mask & other.mask == 0 { if self.check_mask & other.mask == 0 {
return false; return false;
} }
@ -139,7 +138,7 @@ pub struct UpdateShapes;
/// Update collider shapes to match new [`Transform`] /// Update collider shapes to match new [`Transform`]
pub fn update_collider_shapes( pub fn update_collider_shapes(
mut commands: Commands, mut commands: Commands,
colliders: Query<(&mut Collider, &Transform, Entity), With<UpdateShapes>>, colliders: Query<(&mut Collider, &Transform, Entity), Added<UpdateShapes>>,
) { ) {
for (mut collider, transform, entity) in colliders { for (mut collider, transform, entity) in colliders {
collider.update_shapes_position(&transform.translation.xy()); collider.update_shapes_position(&transform.translation.xy());
@ -147,6 +146,16 @@ pub fn update_collider_shapes(
} }
} }
/// Detect new colliders and automatically insert [`UpdateShapes`]
pub fn detect_colliders(
mut commands: Commands,
query: Query<Entity, Added<Collider>>,
) {
for entity in query {
commands.entity(entity).insert(UpdateShapes);
}
}
#[derive(EntityEvent, Debug)] #[derive(EntityEvent, Debug)]
/// Emitted when colliders intersect in [`check_for_collisions`] system /// Emitted when colliders intersect in [`check_for_collisions`] system
pub struct CollisionEvent { pub struct CollisionEvent {
@ -156,21 +165,22 @@ pub struct CollisionEvent {
pub detected: Entity, pub detected: Entity,
} }
fn collider_filter(checker: &&Collider, checkable: &&Collider) -> bool {
checker != checkable && checker.check_mask != 0
}
/// Check each [`Collider`] for collisions with another colliders. /// Check each [`Collider`] for collisions with another colliders.
/// Triggers [`CollisionEvent`] on collider intersection /// Triggers [`CollisionEvent`] on collider intersection
pub fn check_for_collisions( pub fn check_for_collisions(
mut commands: Commands, mut commands: Commands,
colliders: Query<(&Collider, Entity)>, colliders: Query<(&Collider, Entity)>,
) { ) {
let mut visited_colliders: Vec<&Collider> = Vec::new();
for (collider, entity) in colliders.iter() { for (collider, entity) in colliders.iter() {
for (other_collider, other_entity) in colliders.iter().filter(|(c, _)| !visited_colliders.contains(c)) { for (other_collider, other_entity) in colliders.iter().filter(|(c, _)| collider_filter(&collider, c)) {
if collider.intersects(other_collider) { if collider.intersects(other_collider) {
commands.trigger(CollisionEvent { entity, detected: other_entity }); commands.trigger(CollisionEvent { entity, detected: other_entity });
} }
} }
visited_colliders.push(collider);
println!("{visited_colliders:?}");
} }
} }
@ -179,6 +189,6 @@ pub struct CollisionPlugin;
impl Plugin for CollisionPlugin { impl Plugin for CollisionPlugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.add_systems(PostUpdate, (update_collider_shapes, check_for_collisions).chain()); app.add_systems(PostUpdate, (detect_colliders, update_collider_shapes, check_for_collisions).chain());
} }
} }

View file

@ -1,7 +1,7 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy_collision_plugin::{Collider, CollisionEvent, CollisionPlugin, CollisionShape, UpdateShapes}; use bevy_collision_plugin::{Collider, CollisionEvent, CollisionPlugin, CollisionShape, UpdateShapes};
const CHECKED_GROUPS: usize = 1 >> 0 | 1 >> 1; const CHECKED_GROUPS: usize = 1 << 0 | 1 << 1;
#[derive(Component)] #[derive(Component)]
struct MovingCollider; struct MovingCollider;
@ -27,7 +27,7 @@ fn zerogroup_collider_bundle() -> impl Bundle {
shapes: vec![ shapes: vec![
CollisionShape::new_aabb(Vec2::new(0., 0.), Vec2::new(10., 10.)), CollisionShape::new_aabb(Vec2::new(0., 0.), Vec2::new(10., 10.)),
], ],
mask: 1 >> 0, mask: 1 << 0,
check_mask: 0, check_mask: 0,
}, },
Transform::from_translation(Vec3::new(53., 5., 0.)), Transform::from_translation(Vec3::new(53., 5., 0.)),
@ -40,7 +40,7 @@ fn firstgroup_collider_bundle() -> impl Bundle {
shapes: vec![ shapes: vec![
CollisionShape::new_circle(Vec2::new(0., 0.), 5.), CollisionShape::new_circle(Vec2::new(0., 0.), 5.),
], ],
mask: 1 >> 1, mask: 1 << 1,
check_mask: 0, check_mask: 0,
}, },
Transform::from_translation(Vec3::new(53., 18., 0.)), Transform::from_translation(Vec3::new(53., 18., 0.)),
@ -66,7 +66,7 @@ fn setup(
fn configured_app() -> App { fn configured_app() -> App {
let mut app = App::new(); let mut app = App::new();
app.add_plugins(CollisionPlugin) app.add_plugins(CollisionPlugin)
.add_systems(Startup, setup) .add_systems(Startup, setup)
.add_systems(Update, move_collider); .add_systems(Update, move_collider);