avian2d/collision/collider/
mod.rs

1//! Components, traits, and plugins related to collider functionality.
2
3use crate::prelude::*;
4use bevy::{
5    ecs::{
6        component::Mutable,
7        entity::{EntityMapper, MapEntities, hash_set::EntityHashSet},
8        system::{ReadOnlySystemParam, SystemParam, SystemParamItem},
9    },
10    prelude::*,
11};
12use derive_more::From;
13
14mod backend;
15
16pub use backend::{ColliderBackendPlugin, ColliderMarker};
17
18#[cfg(all(feature = "collider-from-mesh", feature = "default-collider"))]
19mod cache;
20#[cfg(all(feature = "collider-from-mesh", feature = "default-collider"))]
21pub use cache::ColliderCachePlugin;
22pub mod collider_hierarchy;
23pub mod collider_transform;
24#[cfg(all(feature = "3d", any(feature = "parry-f32", feature = "parry-f64")))]
25pub mod trimesh_builder;
26
27mod layers;
28pub use layers::*;
29
30/// The default [`Collider`] that uses Parry.
31#[cfg(all(
32    feature = "default-collider",
33    any(feature = "parry-f32", feature = "parry-f64")
34))]
35mod parry;
36#[cfg(all(
37    feature = "default-collider",
38    any(feature = "parry-f32", feature = "parry-f64")
39))]
40pub use parry::*;
41
42#[cfg(feature = "default-collider")]
43mod constructor;
44#[cfg(feature = "default-collider")]
45pub use constructor::{
46    ColliderConstructor, ColliderConstructorHierarchy, ColliderConstructorHierarchyConfig,
47    ColliderConstructorHierarchyReady, ColliderConstructorReady,
48};
49
50/// A trait for creating colliders from other types.
51pub trait IntoCollider<C: AnyCollider> {
52    /// Creates a collider from `self`.
53    fn collider(&self) -> C;
54}
55
56/// Context necessary to calculate [`ColliderAabb`]s for an [`AnyCollider`]
57#[derive(Deref)]
58pub struct AabbContext<'a, 'w, 's, T: ReadOnlySystemParam> {
59    /// The entity for which the aabb is being calculated
60    pub entity: Entity,
61    #[deref]
62    item: &'a SystemParamItem<'w, 's, T>,
63}
64
65impl<T: ReadOnlySystemParam> Clone for AabbContext<'_, '_, '_, T> {
66    fn clone(&self) -> Self {
67        Self {
68            entity: self.entity,
69            item: self.item,
70        }
71    }
72}
73
74impl<'a, 'w, 's, T: ReadOnlySystemParam> AabbContext<'a, 'w, 's, T> {
75    /// Construct an [`AabbContext`]
76    pub fn new(entity: Entity, item: &'a <T as SystemParam>::Item<'w, 's>) -> Self {
77        Self { entity, item }
78    }
79}
80
81impl AabbContext<'_, '_, '_, ()> {
82    fn fake() -> Self {
83        Self {
84            entity: Entity::PLACEHOLDER,
85            item: &(),
86        }
87    }
88}
89
90/// Context necessary to calculate [`ContactManifold`]s for a set of [`AnyCollider`]
91#[derive(Deref)]
92pub struct ContactManifoldContext<'a, 'w, 's, T: ReadOnlySystemParam> {
93    /// The first collider entity involved in the contact.
94    pub entity1: Entity,
95    /// The second collider entity involved in the contact.
96    pub entity2: Entity,
97    #[deref]
98    item: &'a SystemParamItem<'w, 's, T>,
99}
100
101impl<'a, 'w, 's, T: ReadOnlySystemParam> ContactManifoldContext<'a, 'w, 's, T> {
102    /// Construct a [`ContactManifoldContext`]
103    pub fn new(
104        entity1: Entity,
105        entity2: Entity,
106        item: &'a <T as SystemParam>::Item<'w, 's>,
107    ) -> Self {
108        Self {
109            entity1,
110            entity2,
111            item,
112        }
113    }
114}
115
116impl ContactManifoldContext<'_, '_, '_, ()> {
117    fn fake() -> Self {
118        Self {
119            entity1: Entity::PLACEHOLDER,
120            entity2: Entity::PLACEHOLDER,
121            item: &(),
122        }
123    }
124}
125
126/// A trait that generalizes over colliders. Implementing this trait
127/// allows colliders to be used with the physics engine.
128pub trait AnyCollider: Component<Mutability = Mutable> + ComputeMassProperties {
129    /// A type providing additional context for collider operations.
130    ///
131    /// `Context` allows you to access an arbitrary [`ReadOnlySystemParam`] on
132    /// the world, for context-sensitive behavior in collider operations. You
133    /// can use this to query components on the collider entity, or get any
134    /// other necessary context from the world.
135    ///
136    /// # Example
137    ///
138    /// ```
139    #[cfg_attr(
140        feature = "2d",
141        doc = "# use avian2d::{prelude::*, math::{Vector, Scalar}};"
142    )]
143    #[cfg_attr(
144        feature = "3d",
145        doc = "# use avian3d::{prelude::*, math::{Vector, Scalar}};"
146    )]
147    /// # use bevy::prelude::*;
148    /// # use bevy::ecs::system::{SystemParam, lifetimeless::{SRes, SQuery}};
149    /// #
150    /// #[derive(Component)]
151    /// pub struct VoxelCollider;
152    ///
153    /// #[derive(Component)]
154    /// pub struct VoxelData {
155    ///     // collider voxel data...
156    /// }
157    ///
158    /// # impl ComputeMassProperties2d for VoxelCollider {
159    /// #     fn mass(&self, density: f32) -> f32 {0.}
160    /// #     fn unit_angular_inertia(&self) -> f32 { 0.}
161    /// #     fn center_of_mass(&self) -> Vec2 { Vec2::ZERO }
162    /// # }
163    /// #
164    /// # impl ComputeMassProperties3d for VoxelCollider {
165    /// #     fn mass(&self, density: f32) -> f32 {0.}
166    /// #     fn unit_principal_angular_inertia(&self) -> Vec3 { Vec3::ZERO }
167    /// #     fn center_of_mass(&self) -> Vec3 { Vec3::ZERO }
168    /// # }
169    /// #
170    /// impl AnyCollider for VoxelCollider {
171    ///     type Context = (
172    ///         // you can query extra components here
173    ///         SQuery<&'static VoxelData>,
174    ///         // or put any other read-only system param here
175    ///         SRes<Time>,
176    ///     );
177    ///
178    /// #   fn aabb_with_context(
179    /// #       &self,
180    /// #       _: Vector,
181    /// #       _: impl Into<Rotation>,
182    /// #       _: AabbContext<Self::Context>,
183    /// #   ) -> ColliderAabb { unimplemented!() }
184    /// #
185    ///     fn contact_manifolds_with_context(
186    ///         &self,
187    ///         other: &Self,
188    ///         position1: Vector,
189    ///         rotation1: impl Into<Rotation>,
190    ///         position2: Vector,
191    ///         rotation2: impl Into<Rotation>,
192    ///         prediction_distance: Scalar,
193    ///         manifolds: &mut Vec<ContactManifold>,
194    ///         context: ContactManifoldContext<Self::Context>,
195    ///     ) {
196    ///         let [voxels1, voxels2] = context.0.get_many([context.entity1, context.entity2])
197    ///             .expect("our own `VoxelCollider` entities should have `VoxelData`");
198    ///         let elapsed = context.1.elapsed();
199    ///         // do some computation...
200    /// #       unimplemented!()
201    ///     }
202    /// }
203    /// ```
204    type Context: for<'w, 's> ReadOnlySystemParam<Item<'w, 's>: Send + Sync>;
205
206    /// Computes the [Axis-Aligned Bounding Box](ColliderAabb) of the collider
207    /// with the given position and rotation.
208    ///
209    /// See [`SimpleCollider::aabb`] for collider types with empty [`AnyCollider::Context`]
210    #[cfg_attr(
211        feature = "2d",
212        doc = "\n\nThe rotation is counterclockwise and in radians."
213    )]
214    fn aabb_with_context(
215        &self,
216        position: Vector,
217        rotation: impl Into<Rotation>,
218        context: AabbContext<Self::Context>,
219    ) -> ColliderAabb;
220
221    /// Computes the swept [Axis-Aligned Bounding Box](ColliderAabb) of the collider.
222    /// This corresponds to the space the shape would occupy if it moved from the given
223    /// start position to the given end position.
224    ///
225    /// See [`SimpleCollider::swept_aabb`] for collider types with empty [`AnyCollider::Context`]
226    #[cfg_attr(
227        feature = "2d",
228        doc = "\n\nThe rotation is counterclockwise and in radians."
229    )]
230    fn swept_aabb_with_context(
231        &self,
232        start_position: Vector,
233        start_rotation: impl Into<Rotation>,
234        end_position: Vector,
235        end_rotation: impl Into<Rotation>,
236        context: AabbContext<Self::Context>,
237    ) -> ColliderAabb {
238        self.aabb_with_context(start_position, start_rotation, context.clone())
239            .merged(self.aabb_with_context(end_position, end_rotation, context))
240    }
241
242    /// Computes all [`ContactManifold`]s between two colliders.
243    ///
244    /// Returns an empty vector if the colliders are separated by a distance greater than `prediction_distance`
245    /// or if the given shapes are invalid.
246    ///
247    /// See [`SimpleCollider::contact_manifolds`] for collider types with empty [`AnyCollider::Context`]
248    fn contact_manifolds_with_context(
249        &self,
250        other: &Self,
251        position1: Vector,
252        rotation1: impl Into<Rotation>,
253        position2: Vector,
254        rotation2: impl Into<Rotation>,
255        prediction_distance: Scalar,
256        manifolds: &mut Vec<ContactManifold>,
257        context: ContactManifoldContext<Self::Context>,
258    );
259}
260
261/// A simplified wrapper around [`AnyCollider`] that doesn't require passing in the context for
262/// implementations that don't need context
263pub trait SimpleCollider: AnyCollider<Context = ()> {
264    /// Computes the [Axis-Aligned Bounding Box](ColliderAabb) of the collider
265    /// with the given position and rotation.
266    ///
267    /// See [`AnyCollider::aabb_with_context`] for collider types with non-empty [`AnyCollider::Context`]
268    fn aabb(&self, position: Vector, rotation: impl Into<Rotation>) -> ColliderAabb {
269        self.aabb_with_context(position, rotation, AabbContext::fake())
270    }
271
272    /// Computes the swept [Axis-Aligned Bounding Box](ColliderAabb) of the collider.
273    /// This corresponds to the space the shape would occupy if it moved from the given
274    /// start position to the given end position.
275    ///
276    /// See [`AnyCollider::swept_aabb_with_context`] for collider types with non-empty [`AnyCollider::Context`]
277    fn swept_aabb(
278        &self,
279        start_position: Vector,
280        start_rotation: impl Into<Rotation>,
281        end_position: Vector,
282        end_rotation: impl Into<Rotation>,
283    ) -> ColliderAabb {
284        self.swept_aabb_with_context(
285            start_position,
286            start_rotation,
287            end_position,
288            end_rotation,
289            AabbContext::fake(),
290        )
291    }
292
293    /// Computes all [`ContactManifold`]s between two colliders, writing the results into `manifolds`.
294    ///
295    /// `manifolds` is cleared if the colliders are separated by a distance greater than `prediction_distance`
296    /// or if the given shapes are invalid.
297    ///
298    /// See [`AnyCollider::contact_manifolds_with_context`] for collider types with non-empty [`AnyCollider::Context`]
299    fn contact_manifolds(
300        &self,
301        other: &Self,
302        position1: Vector,
303        rotation1: impl Into<Rotation>,
304        position2: Vector,
305        rotation2: impl Into<Rotation>,
306        prediction_distance: Scalar,
307        manifolds: &mut Vec<ContactManifold>,
308    ) {
309        self.contact_manifolds_with_context(
310            other,
311            position1,
312            rotation1,
313            position2,
314            rotation2,
315            prediction_distance,
316            manifolds,
317            ContactManifoldContext::fake(),
318        )
319    }
320}
321
322impl<C: AnyCollider<Context = ()>> SimpleCollider for C {}
323
324/// A trait for colliders that support scaling.
325pub trait ScalableCollider: AnyCollider {
326    /// Returns the global scaling factor of the collider.
327    fn scale(&self) -> Vector;
328
329    /// Sets the global scaling factor of the collider.
330    ///
331    /// If the scaling factor is not uniform and the resulting scaled shape
332    /// can not be represented exactly, the given `detail` is used for an approximation.
333    fn set_scale(&mut self, scale: Vector, detail: u32);
334
335    /// Scales the collider by the given scaling factor.
336    ///
337    /// If the scaling factor is not uniform and the resulting scaled shape
338    /// can not be represented exactly, the given `detail` is used for an approximation.
339    fn scale_by(&mut self, factor: Vector, detail: u32) {
340        self.set_scale(factor * self.scale(), detail)
341    }
342}
343
344/// A marker component that indicates that a [collider](Collider) is disabled
345/// and should not detect collisions or be included in spatial queries.
346///
347/// This is useful for temporarily disabling a collider without removing it from the world.
348/// To re-enable the collider, simply remove this component.
349///
350/// Note that a disabled collider will still contribute to the mass properties of the rigid body
351/// it is attached to. Set the [`Mass`] of the collider to zero to prevent this.
352///
353/// [`ColliderDisabled`] only applies to the entity it is attached to, not its children.
354///
355/// # Example
356///
357/// ```
358#[cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
359#[cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
360/// # use bevy::prelude::*;
361/// #
362/// #[derive(Component)]
363/// pub struct Character;
364///
365/// /// Disables colliders for all rigid body characters, for example during cutscenes.
366/// fn disable_character_colliders(
367///     mut commands: Commands,
368///     query: Query<Entity, (With<RigidBody>, With<Character>)>,
369/// ) {
370///     for entity in &query {
371///         commands.entity(entity).insert(ColliderDisabled);
372///     }
373/// }
374///
375/// /// Enables colliders for all rigid body characters.
376/// fn enable_character_colliders(
377///     mut commands: Commands,
378///     query: Query<Entity, (With<RigidBody>, With<Character>)>,
379/// ) {
380///     for entity in &query {
381///         commands.entity(entity).remove::<ColliderDisabled>();
382///     }
383/// }
384/// ```
385///
386/// # Related Components
387///
388/// - [`RigidBodyDisabled`]: Disables a rigid body.
389/// - [`JointDisabled`]: Disables a joint constraint.
390#[derive(Reflect, Clone, Copy, Component, Debug, Default)]
391#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
392#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
393#[reflect(Debug, Component, Default)]
394pub struct ColliderDisabled;
395
396/// A component that marks a [`Collider`] as a sensor, also known as a trigger.
397///
398/// Sensor colliders send [collision events](crate::collision#collision-events) and register intersections,
399/// but allow other bodies to pass through them. This is often used to detect when something enters
400/// or leaves an area or is intersecting some shape.
401///
402/// Sensor colliders do *not* contribute to the mass properties of rigid bodies.
403///
404/// # Example
405///
406/// ```
407#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
408#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
409/// use bevy::prelude::*;
410///
411/// fn setup(mut commands: Commands) {
412///     // Spawn a static body with a sensor collider.
413///     // Other bodies will pass through, but it will still send collision events.
414#[cfg_attr(
415    feature = "2d",
416    doc = "    commands.spawn((RigidBody::Static, Collider::circle(0.5), Sensor));"
417)]
418#[cfg_attr(
419    feature = "3d",
420    doc = "    commands.spawn((RigidBody::Static, Collider::sphere(0.5), Sensor));"
421)]
422/// }
423/// ```
424#[doc(alias = "Trigger")]
425#[derive(Reflect, Clone, Component, Debug, Default, PartialEq, Eq)]
426#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
427#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
428#[reflect(Debug, Component, Default, PartialEq)]
429pub struct Sensor;
430
431/// The Axis-Aligned Bounding Box of a [collider](Collider) in world space.
432///
433/// This is updated automatically.
434#[derive(Reflect, Clone, Copy, Component, Debug, PartialEq)]
435#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
436#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
437#[reflect(Debug, Component, PartialEq)]
438pub struct ColliderAabb {
439    /// The minimum point of the AABB.
440    pub min: Vector,
441    /// The maximum point of the AABB.
442    pub max: Vector,
443}
444
445impl Default for ColliderAabb {
446    fn default() -> Self {
447        ColliderAabb::INVALID
448    }
449}
450
451impl ColliderAabb {
452    /// An invalid [`ColliderAabb`] that represents an empty AABB.
453    pub const INVALID: Self = Self {
454        min: Vector::INFINITY,
455        max: Vector::NEG_INFINITY,
456    };
457
458    /// Creates a new [`ColliderAabb`] from the given `center` and `half_size`.
459    pub fn new(center: Vector, half_size: Vector) -> Self {
460        Self {
461            min: center - half_size,
462            max: center + half_size,
463        }
464    }
465
466    /// Creates a new [`ColliderAabb`] from its minimum and maximum points.
467    pub fn from_min_max(min: Vector, max: Vector) -> Self {
468        Self { min, max }
469    }
470
471    /// Creates a new [`ColliderAabb`] from a given `SharedShape`.
472    #[cfg(all(
473        feature = "default-collider",
474        any(feature = "parry-f32", feature = "parry-f64")
475    ))]
476    pub fn from_shape(shape: &crate::parry::shape::SharedShape) -> Self {
477        let aabb = shape.compute_local_aabb();
478        Self {
479            min: aabb.mins,
480            max: aabb.maxs,
481        }
482    }
483
484    /// Computes the center of the AABB,
485    #[inline(always)]
486    pub fn center(self) -> Vector {
487        self.min.midpoint(self.max)
488    }
489
490    /// Computes the size of the AABB.
491    #[inline(always)]
492    pub fn size(self) -> Vector {
493        self.max - self.min
494    }
495
496    /// Merges this AABB with another one.
497    #[inline(always)]
498    pub fn merged(self, other: Self) -> Self {
499        ColliderAabb {
500            min: self.min.min(other.min),
501            max: self.max.max(other.max),
502        }
503    }
504
505    /// Increases the size of the bounding volume in each direction by the given amount.
506    #[inline(always)]
507    pub fn grow(&self, amount: Vector) -> Self {
508        let b = Self {
509            min: self.min - amount,
510            max: self.max + amount,
511        };
512        debug_assert!(b.min.cmple(b.max).all());
513        b
514    }
515
516    /// Decreases the size of the bounding volume in each direction by the given amount.
517    #[inline(always)]
518    pub fn shrink(&self, amount: Vector) -> Self {
519        let b = Self {
520            min: self.min + amount,
521            max: self.max - amount,
522        };
523        debug_assert!(b.min.cmple(b.max).all());
524        b
525    }
526
527    /// Checks if `self` intersects with `other`.
528    #[inline(always)]
529    #[cfg(feature = "2d")]
530    pub fn intersects(&self, other: &Self) -> bool {
531        let x_overlaps = self.min.x <= other.max.x && self.max.x >= other.min.x;
532        let y_overlaps = self.min.y <= other.max.y && self.max.y >= other.min.y;
533        x_overlaps && y_overlaps
534    }
535
536    /// Checks if `self` intersects with `other`.
537    #[inline(always)]
538    #[cfg(feature = "3d")]
539    pub fn intersects(&self, other: &Self) -> bool {
540        let x_overlaps = self.min.x <= other.max.x && self.max.x >= other.min.x;
541        let y_overlaps = self.min.y <= other.max.y && self.max.y >= other.min.y;
542        let z_overlaps = self.min.z <= other.max.z && self.max.z >= other.min.z;
543        x_overlaps && y_overlaps && z_overlaps
544    }
545
546    /// Checks if `self` contains `other`.
547    #[inline(always)]
548    pub fn contains(&self, other: &Self) -> bool {
549        self.min.cmple(other.min).all() && self.max.cmpge(other.max).all()
550    }
551}
552
553impl From<ColliderAabb> for obvhs::aabb::Aabb {
554    fn from(value: ColliderAabb) -> Self {
555        Self {
556            #[cfg(feature = "2d")]
557            min: value.min.f32().extend(-0.5).to_array().into(),
558            #[cfg(feature = "2d")]
559            max: value.max.f32().extend(0.5).to_array().into(),
560            #[cfg(feature = "3d")]
561            min: value.min.f32().to_array().into(),
562            #[cfg(feature = "3d")]
563            max: value.max.f32().to_array().into(),
564        }
565    }
566}
567
568/// An Axis-Aligned Bounding Box that contains the [`ColliderAabb`] with an additional margin.
569///
570/// This is used to avoid updating the Bounding Volume Hierarchy acceleration structure
571/// every time a collider moves only a small amount.
572///
573/// The enlarged AABB is updated automatically whenever the [`ColliderAabb`]
574/// moves beyond the bounds of the current enlarged AABB.
575#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, PartialEq)]
576#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
577#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
578#[reflect(Debug, Component, PartialEq)]
579pub struct EnlargedAabb(ColliderAabb);
580
581impl EnlargedAabb {
582    /// Creates a new [`EnlargedAabb`] from the given [`ColliderAabb`].
583    pub fn new(aabb: ColliderAabb) -> Self {
584        Self(aabb)
585    }
586
587    /// Updates the enlarged AABB with the given [`ColliderAabb`] and margin.
588    ///
589    /// If the AABB is already contained within the enlarged AABB, nothing happens.
590    ///
591    /// Returns `true` if the AABB was updated.
592    pub fn update(&mut self, aabb: &ColliderAabb, margin: Scalar) -> bool {
593        if self.contains(aabb) {
594            return false;
595        }
596
597        let margin = Vector::splat(margin);
598        self.0.min = aabb.min - margin;
599        self.0.max = aabb.max + margin;
600
601        true
602    }
603
604    /// Gets the [`ColliderAabb`] of the enlarged AABB.
605    pub fn get(&self) -> ColliderAabb {
606        self.0
607    }
608}
609
610/// A component that adds an extra margin or "skin" around [`Collider`] shapes to help maintain
611/// additional separation to other objects. This added thickness can help improve
612/// stability and performance in some cases, especially for thin shapes such as trimeshes.
613///
614/// There are three primary reasons for collision margins:
615///
616/// 1. Collision detection is often more efficient when shapes are not overlapping
617/// further than their collision margins. Deeply overlapping shapes require
618/// more expensive collision algorithms.
619///
620/// 2. Some shapes such as triangles and planes are infinitely thin,
621/// which can cause precision errors. A collision margin adds artificial
622/// thickness to shapes, improving stability.
623///
624/// 3. Overall, collision margins give the physics engine more
625/// room for error when resolving contacts. This can also help
626/// prevent visible artifacts such as objects poking through the ground.
627///
628/// If a rigid body with a [`CollisionMargin`] has colliders as child entities,
629/// and those colliders don't have their own [`CollisionMargin`] components,
630/// the colliders will use the rigid body's [`CollisionMargin`].
631///
632/// # Example
633///
634/// ```
635#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
636#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
637/// use bevy::prelude::*;
638///
639/// fn setup(mut commands: Commands) {
640#[cfg_attr(
641    feature = "2d",
642    doc = "    // Spawn a rigid body with a collider.
643    // A margin of `0.1` is added around the shape.
644    commands.spawn((
645        RigidBody::Dynamic,
646        Collider::capsule(2.0, 0.5),
647        CollisionMargin(0.1),
648    ));"
649)]
650#[cfg_attr(
651    feature = "3d",
652    doc = "    let mesh = Mesh::from(Torus::default());
653
654    // Spawn a rigid body with a triangle mesh collider.
655    // A margin of `0.1` is added around the shape.
656    commands.spawn((
657        RigidBody::Dynamic,
658        Collider::trimesh_from_mesh(&mesh).unwrap(),
659        CollisionMargin(0.1),
660    ));"
661)]
662/// }
663/// ```
664#[derive(Reflect, Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq, From)]
665#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
666#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
667#[reflect(Component)]
668#[doc(alias = "ContactSkin")]
669pub struct CollisionMargin(pub Scalar);
670
671/// A component for reading which entities are colliding with a collider entity.
672/// Must be added manually for desired colliders.
673///
674/// # Example
675///
676/// ```
677#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
678#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
679/// use bevy::prelude::*;
680///
681/// fn setup(mut commands: Commands) {
682///     commands.spawn((
683///         RigidBody::Dynamic,
684///         Collider::capsule(0.5, 1.5),
685///         // Add the `CollidingEntities` component to read entities colliding with this entity.
686///         CollidingEntities::default(),
687///     ));
688/// }
689///
690/// fn my_system(query: Query<(Entity, &CollidingEntities)>) {
691///     for (entity, colliding_entities) in &query {
692///         println!(
693///             "{} is colliding with the following entities: {:?}",
694///             entity,
695///             colliding_entities,
696///         );
697///     }
698/// }
699/// ```
700#[derive(Reflect, Clone, Component, Debug, Default, Deref, DerefMut, PartialEq, Eq)]
701#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
702#[cfg_attr(feature = "serialize", reflect(Serialize, Deserialize))]
703#[reflect(Debug, Component, Default, PartialEq)]
704pub struct CollidingEntities(pub EntityHashSet);
705
706impl MapEntities for CollidingEntities {
707    fn map_entities<M: EntityMapper>(&mut self, entity_mapper: &mut M) {
708        self.0 = self
709            .0
710            .clone()
711            .into_iter()
712            .map(|e| entity_mapper.get_mapped(e))
713            .collect()
714    }
715}