Jondolf / avian

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

Issue with sphere on slope #408

Open Maybells opened 2 months ago

Maybells commented 2 months ago

When I spawn a ball above a slope, it falls onto it due to gravity, but then just jitters in place. Adjusting the angle of the slope creates other unintended behaviors, such as veering the side and then stopping completely.

My code is as follows:

// Ball
commands
        .spawn(PbrBundle {
            mesh: meshes.add(Sphere::default().mesh()),
            material: materials.add(Color::linear_rgb(1., 0., 0.)),
            transform: Transform::from_xyz(0., 2., 0.),
            ..default()
        })
        .insert(RigidBody::Dynamic)
        .insert(Collider::sphere(0.5));

// Ramp
commands
        .spawn(PbrBundle {
            mesh: meshes.add(Plane3d::default().mesh().size(20., 20.)),
            material: materials.add(Color::WHITE),
            transform: Transform::from_xyz(0., 1., 0.)
                .with_rotation(Quat::from_rotation_x(PI / 30.0)),
            ..default()
        })
        .insert(RigidBody::Static)
        .insert(Collider::cuboid(20., 0.1, 20.));

Everything else is the same as the example in the Readme.

Jondolf commented 2 months ago

Hi! It seems like I'm not able to reproduce this behavior...

My code ```rust use avian3d::{math::PI, prelude::*}; use bevy::prelude::*; fn main() { App::new() // Enable physics .add_plugins((DefaultPlugins, PhysicsPlugins::default())) .add_systems(Startup, setup) .run(); } fn setup( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, ) { // Ball commands .spawn(PbrBundle { mesh: meshes.add(Sphere::default().mesh()), material: materials.add(Color::linear_rgb(1., 0., 0.)), transform: Transform::from_xyz(0., 2., 0.), ..default() }) .insert(RigidBody::Dynamic) .insert(Collider::sphere(0.5)); // Ramp commands .spawn(PbrBundle { mesh: meshes.add(Plane3d::default().mesh().size(20., 20.)), material: materials.add(Color::WHITE), transform: Transform::from_xyz(0., 1., 0.) .with_rotation(Quat::from_rotation_x(PI / 30.0)), ..default() }) .insert(RigidBody::Static) .insert(Collider::cuboid(20., 0.1, 20.)); // Light commands.spawn(PointLightBundle { point_light: PointLight { shadows_enabled: true, ..default() }, transform: Transform::from_xyz(4.0, 8.0, 4.0), ..default() }); // Camera commands.spawn(Camera3dBundle { transform: Transform::from_xyz(-10.5, 15.5, 20.0).looking_at(Vec3::ZERO, Dir3::Y), ..default() }); } ```

https://github.com/Jondolf/avian/assets/57632562/d06a561c-28f1-4fa0-8eec-ed40f95aefa7

I have also tried several different slope angles, and don't have any veering to the side. If you have the ball roll very slowly though, it might be getting marked as sleeping to save computational resources. That could be disabled with SleepingDisabled.

What's your exact setup?

Maybells commented 2 months ago
use std::f32::consts::PI;

use avian3d::prelude::*;
use bevy::prelude::*;

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

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
    assets: Res<AssetServer>,
) {
    // Camera
    commands.spawn(Camera3dBundle {
        transform: Transform::from_xyz(0.0, 12., 24.0).looking_at(Vec3::new(0., 1., 0.), Vec3::Y),
        ..default()
    });

    // Light Source
    commands.spawn(PointLightBundle {
        point_light: PointLight {
            shadows_enabled: true,
            intensity: 10_000_000.,
            range: 100.0,
            ..default()
        },
        transform: Transform::from_xyz(8.0, 16.0, 8.0),
        ..default()
    });

    // Floor
    commands.spawn(PbrBundle {
        mesh: meshes.add(Plane3d::default().mesh().size(50., 50.)),
        material: materials.add(Color::linear_rgb(0.45, 0.45, 0.45)),
        ..default()
    });

    // Ball
    commands
        .spawn(PbrBundle {
            mesh: meshes.add(Sphere::default().mesh()),
            material: materials.add(Color::linear_rgb(1., 0., 0.)),
            transform: Transform::from_xyz(0., 2., 0.),
            ..default()
        })
        .insert(RigidBody::Dynamic)
        .insert(Collider::sphere(0.5));

    // Ramp
    commands
        .spawn(PbrBundle {
            mesh: meshes.add(Plane3d::default().mesh().size(20., 20.)),
            material: materials.add(Color::WHITE),
            transform: Transform::from_xyz(0., 1., 0.)
                .with_rotation(Quat::from_rotation_x(PI / 30.0)),
            ..default()
        })
        .insert(RigidBody::Static)
        .insert(Collider::cuboid(20., 0.1, 20.))
        .with_children(|parent| {
            // // Paddle
            let paddle_gltf = assets.load(GltfAssetLabel::Scene(0).from_asset("pinball.glb"));
            parent
            .spawn((
                SceneBundle {
                    scene: paddle_gltf,
                    transform: Transform::from_xyz(-3., 0., 6.),
                    ..default()
                },
                ColliderConstructorHierarchy::new(ColliderConstructor::TrimeshFromMesh),
            ))
            .insert(RigidBody::Kinematic);
        });
}

I think the issue is the combination of ColliderConstructorHierarchy::new(ColliderConstructor::TrimeshFromMesh) and being a child of the ramp. When I used a Collider::sphere(0.5) instead everything worked (apart from the pinball paddle having the wrong collider shape), and when I had the paddle as its own entity with no parent, it also worked. I left out a system for handling player input and rotating the paddle, but I don't think it's relevant since the issue still happens if I disable it.

Khanoto commented 1 month ago

I think when your sphere fall on the plane, it apply a force on it and its childrens.

Of course it should not move if your plane is static, but the force may be applied to the child object, which make the sphere fall again as soon as it hit the plane, which make it seem like it's jittering. (I'm not sure about what I say, just a guess)

I'm not sure to understand why you would need your sphere to be a child of the ramp though.