Closed Easyoakland closed 6 days ago
Hi! This an expect consequence of the incremental constraints solver. This will generally result in uneven forces at all four contact points. So even if all of these forces are along +Y, the result in a non-zero torque (creating a rotation). The accurate way to fix that is by solving all four constraints simultaneously which is extremely complex and expensive in 3D (we do this in 2D though, resolving two constraints simultaneously).
The alternative is to increase the number of solver iterations, but this is often not worth the performance impact.
When spawning a cuboid symmetric about x and z and letting it fall due to gravity onto a plane also symmetric about x and z it bounces asymmetrically about x and z. This is strange because the contact force is only in the y direction but yet the cuboid moves in x, y, and z and changes rotation.
Surely the cuboid should only move along the y-axis without rotation due to symmetry and the force only pointing along the y-axis?
In the following example you can see this effect resulting in one of the corners hitting the y=0 plane before the opposite on the second bounce.
Minimal reproducible example
```rust use bevy::{ecs::schedule::ScheduleLabel, input::common_conditions::input_pressed, prelude::*}; use bevy_rapier3d::prelude::*; #[derive(Debug, Hash, PartialEq, Eq, Clone, ScheduleLabel)] struct PhysicsSchedule; fn setup_physics(mut commands: Commands) { // Spawn camera commands.spawn(Camera3dBundle { transform: Transform::from_xyz(0.0, 6., 20.0).looking_at(Vec3::new(0., 1., 0.), Vec3::Y), ..default() }); // Create the ground. let _ground = commands .spawn(Collider::cuboid(5000.0, 0.50, 5000.0)) .insert(TransformBundle::from(Transform::from_xyz(0.0, 0.0, 0.0))) .id(); // Create box let boxy = commands .spawn(( RigidBody::Dynamic, Collider::cuboid(0.06 * 100., 2.0, 0.06 * 100.), Restitution::coefficient(0.5), TransformBundle::from(Transform::from_xyz(0., 6., 0.)), ActiveEvents::all(), ContactForceEventThreshold(0.), )) .id(); // Print box's transform and collision forces to stderr commands.add(move |world: &mut World| { world.schedule_scope(Update, move |_world, schedule| { schedule.add_systems(move |q: Query<&Transform, Changed