Skip to content

Add sending collision events and contact force to observersΒ #644

@Maksych

Description

@Maksych

Let's talk about adding send collision events and contact force to observers.

I think this can be added into src/plugin/context/mod.rs in RapierContextSimulation::send_bevy_events.

We can declare new events, maybe something like this:

/// Event occurring when two colliders start colliding
/// This will only get triggered if the entity has the
/// [`ActiveEvents::COLLISION_EVENTS`] flag enabled.
#[derive(Event, Copy, Clone, Debug, PartialEq, Eq)]
pub struct CollisionStarted {
    pub collider: Entity,
    pub flags: CollisionEventFlags,
}

/// Event occurring when two colliders stop colliding
/// This will only get triggered if the entity has the
/// [`ActiveEvents::COLLISION_EVENTS`] flag enabled.
#[derive(Event, Copy, Clone, Debug, PartialEq, Eq)]
pub struct CollisionStopped {
    pub collider: Entity,
    pub flags: CollisionEventFlags,
}

/// Event occurring when the sum of the magnitudes of the contact forces
/// between two colliders exceed a threshold ([`ContactForceEventThreshold`]).
///
/// This will only get triggered if the entity has the
/// [`ActiveEvents::CONTACT_FORCE_EVENTS`] flag enabled.
#[derive(Event, Copy, Clone, Debug, PartialEq)]
pub struct ContactForce {
    /// Collider involved in the contact.
    pub collider: Entity,
    /// The sum of all the forces between the two colliders.
    pub total_force: Vect,
    /// The sum of the magnitudes of each force between the two colliders.
    ///
    /// Note that this is **not** the same as the magnitude of `self.total_force`.
    /// Here we are summing the magnitude of all the forces, instead of taking
    /// the magnitude of their sum.
    pub total_force_magnitude: Real,
    /// The world-space (unit) direction of the force with strongest magnitude.
    pub max_force_direction: Vect,
    /// The magnitude of the largest force at a contact point of this contact pair.
    pub max_force_magnitude: Real,
}

Then use this new events in src/plugin/context/mod.rs in RapierContextSimulation::send_bevy_events:

/// Generates bevy events for any physics interactions that have happened
    /// that are stored in the events list
    pub fn send_bevy_events(
        &mut self,
        commands: &mut Commands,
        collision_event_writer: &mut EventWriter<CollisionEvent>,
        contact_force_event_writer: &mut EventWriter<ContactForceEvent>,
    ) {
        for collision_event in self.collision_events_to_send.drain(..) {
            collision_event_writer.send(collision_event);

            match collision_event {
                CollisionEvent::Started(entity1, entity2, flags) => {
                    commands.trigger_targets(
                        CollisionStarted {
                            collider: entity2,
                            flags,
                        },
                        entity1,
                    );
                    commands.trigger_targets(
                        CollisionStarted {
                            collider: entity1,
                            flags,
                        },
                        entity2,
                    );
                }
                CollisionEvent::Stopped(entity1, entity2, flags) => {
                    commands.trigger_targets(
                        CollisionStopped {
                            collider: entity2,
                            flags,
                        },
                        entity1,
                    );
                    commands.trigger_targets(
                        CollisionStopped {
                            collider: entity1,
                            flags,
                        },
                        entity2,
                    );
                }
            }
        }

        for contact_force_event in self.contact_force_events_to_send.drain(..) {
            contact_force_event_writer.send(contact_force_event);

            commands.trigger_targets(
                ContactForce {
                    collider: contact_force_event.collider2,
                    total_force: contact_force_event.total_force,
                    total_force_magnitude: contact_force_event.total_force_magnitude,
                    max_force_direction: contact_force_event.max_force_direction,
                    max_force_magnitude: contact_force_event.max_force_magnitude,
                },
                contact_force_event.collider1,
            );

            commands.trigger_targets(
                ContactForce {
                    collider: contact_force_event.collider1,
                    total_force: contact_force_event.total_force,
                    total_force_magnitude: contact_force_event.total_force_magnitude,
                    max_force_direction: contact_force_event.max_force_direction,
                    max_force_magnitude: contact_force_event.max_force_magnitude,
                },
                contact_force_event.collider2,
            );
        }
    }

This may not be the best place to do it, but we need to start this discussion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions