Jondolf / avian

ECS-driven 2D and 3D physics engine for the Bevy game engine.
https://crates.io/crates/avian3d
Apache License 2.0
1.49k stars 119 forks source link

Scaling of parent entity not effecting child collider #289

Closed benjamin-cates closed 1 month ago

benjamin-cates commented 10 months ago

Hello! Just wanted to say I think this repository is really cool but I have found a bug.

Basically, colliders are not effected by the scale transformation of a parent object, even though meshes and everything else are.

Here is a minimal, but still long, example

Cargo.toml:

[package]
name = "bevy_xpbd_scaling_bug"
version = "0.1.0"
edition = "2021"

[dependencies]
bevy = "0.12.1"
bevy_xpbd_3d = "0.3.2"

src/main.rs:

use bevy::prelude::*;
use bevy_xpbd_3d::prelude::*;

fn spawn_objects(
    mut commands: Commands,
    mut materials: ResMut<Assets<StandardMaterial>>,
    mut meshes: ResMut<Assets<Mesh>>,
    mut animations: ResMut<Assets<AnimationClip>>,
) {
    // Spawn camera looking at origin
    commands.spawn((Camera3dBundle {
        transform: Transform::from_xyz(10., 3., 5.).looking_at(Vec3::ZERO, Vec3::Y),
        ..default()
    },));

    // Spawn static 2 by 2 plane collider with 2 by 2 mesh
    let collider = commands
        .spawn((
            Collider::cuboid(2.0, 0.1, 2.0),
            RigidBody::Static,
            PbrBundle {
                mesh: meshes.add(shape::Plane {size: 2.0, subdivisions: 5}.into()),
                material: materials.add(StandardMaterial {
                    emissive: Color::rgb(1., 1., 0.),
                    ..default()
                }),..default()})).id();

    // Spawn empty object and add collider as child
    // Also insert animation that scales it
    let name = Name::new("name");
    commands
        .spawn(SpatialBundle::default())
        .insert(name.clone())
        .add_child(collider)
        .insert({
            let mut player = AnimationPlayer::default();
            let mut animation = AnimationClip::default();
            animation.add_curve_to_path(
                EntityPath {parts: vec![name.clone()]},
                VariableCurve {
                    keyframe_timestamps: vec![0.0, 5.0, 10.0, 100000.0],
                    keyframes: Keyframes::Scale(vec![
                        Vec3::new(1.0, 1.0, 1.0),
                        Vec3::new(5.0, 5.0, 5.0),
                        Vec3::new(2.0, 2.0, 2.0),
                        Vec3::new(2.0, 2.0, 2.0),
                    ]),
                },
            );
            player.play(animations.add(animation));
            player
        });
}

fn main() {
    App::new()
        .add_plugins((DefaultPlugins, PhysicsPlugins::default(), PhysicsDebugPlugin::default()))
        .add_systems(Startup, spawn_objects)
        .run();
}

If you run the example, there is a plane in the middle of the screen that initially starts with a mesh and a collider having the same size. The empty parent of this plane then does a scale animation. The mesh of the child changes in size, but the collider of the child does not.

Photo of the debug render: image

I originally experienced this when I had a box with an open top made of 5 colliders that were children of an empty entity. When I scaled the parent, the positions of the colliders changed so that they were still in line with the walls, but their size did not grow to fill the edges.

I'm willing to submit a pull request to fix this but if someone could give me some guidance on where to look that would be nice. Or if someone knows how to fix it already.

czettnersandor commented 10 months ago

It's probably linked to #288 If you add a RigidBody to the entity, the collider is scaling with the entity, otherwise all transforms on the entity won't be applied to the collider.

It's not only scale, but position and rotation as well.

A workaround for me was to add a static RigidBody to the entity.

benjamin-cates commented 10 months ago

Hmmm this does not fix the issue for me. I added RigidBody::Static to the parent element and it still did not scale appropriately. However the example does work if I change Keyframes::Scale to Keyframes::Translation, whether a RigidBody is present on the parent or not. So this seems to only affect scale and it does not depend on the RigidBody of the parent. So due to this experimentation, I don't think the issues are linked.

janhohenheim commented 8 months ago

Can confirm that the reported workaround does not work for me either

janhohenheim commented 1 month ago

@Jondolf I'm pretty sure you fixed this a while ago, sans the case for negative scales, but those have an own issue.