Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Children entity collision handling is *weird*. #261

Open
ashirviskas opened this issue Nov 23, 2023 · 1 comment
Open

Children entity collision handling is *weird*. #261

ashirviskas opened this issue Nov 23, 2023 · 1 comment

Comments

@ashirviskas
Copy link

I've uncountered some interesting collision handling behaviour and I am not sure if it is an error on my part, or a bug in bevy_xpbd.

I have entities that have Vision. I implement Vision, by spawning a circle with radius X collider as a child of an Entity (craber), in the middle of the Entity (craber).

I want to catch when other entities (Food) get into the vision (anywhere in the radius X) and I found a way of doing that by using xpbd's SpatialQuery.shape_intersections. However, it was very costly, so I implemented it in such a way, that would only check for intersections if a Food entity has entered the Vision via Collision. However, it seems, that the Collision event between Vision and Food only happens at a craber spawning time. It does not happen at any other times.

Here is the relevant code (excuse how messy it is):

  1. Craber with Vision spawning link
  2. Food spawning link
  3. Checking for collisions link
@TeamDman
Copy link
Contributor

I have made a nice reproduction of the weirdness

In my example, the character is the parent of both the pressure plate and the hand. As the character moves, its position and transform are both updated, but on the children only the transform is updated. This results in the children visually following the parent while the physics position not following the parent.

If the child has a velocity, the physics logic takes priority and overwrites the transform, resulting in the child moving with a velocity independent of the parent's velocity.

In the example, I have added ghosts to show the difference between the transform and the position

child_sensor_81wsXsbMJi.mp4

This is all related to the decision to use components instead of Transform to handle the physics (#16 and #96)

/// When synchronizing changes in [`Position`] or [`Rotation`] to `Transform`,
/// the engine treats nested [rigid bodies](RigidBody) as a flat structure. This means that
/// the bodies move independently of the parents, and moving the parent will not affect the child.
///
/// If you would like a child entity to be rigidly attached to its parent, you could use a [`FixedJoint`]
/// or write your own system to handle hierarchies differently.

ref

Here's a naïve attempt at inheriting the parent velocity. I changed the pressure plate from static to dynamic so that it also receives a velocity component that we can update.

fn inherit_velocity(
    mut kids: Query<(&mut LinearVelocity, &mut AngularVelocity, &Parent), Without<Character>>,
    parents: Query<(&LinearVelocity, &AngularVelocity), With<Character>>,
) {
    for (mut kid_linear_velocity, mut kid_angular_velocity, parent) in &mut kids.iter_mut() {
        if let Ok((parent_linear_velocity, parent_angular_velocity)) = parents.get(parent.get()) {
            kid_linear_velocity.x = parent_linear_velocity.x;
            kid_linear_velocity.y = parent_linear_velocity.y;
            kid_angular_velocity.0 = parent_angular_velocity.0;
        }
    }
}
child_sensor_d2hakh2r1j.mp4

This breaks the hand movement logic because the acceleration from its inputs gets clobbered when inheriting the parent velocity. Additionally, this would cause the children to rotate in place rather than pivoting around the parent.

Overall, the decision to have separate components instead of using Transform is because the physics system is inherently flat rather than hierarchical. The ECS itself is also flat, with Parent and Children being conveniences. Using a joint, as recommended by the code comment, is probably the best way to solve this issue.

If you're going to manually adjust transforms to have entities follow another, watch out for: Jitter when making the camera follow a physics object

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants