dimforge / dimforge/bevy_rapier

Inaccurate collisions when using a lot of `ColliderShape`s with the same height

Open
#124 2 comments 0 reactions 0 assignees View on GitHub
A-Dynamics C-Bug D-Difficult P-Medium S-not-started
Dominant language
Rust
Stars
1.6k
Forks
282
PR merge metrics
No merged PRs in 30d

Description

When programming a simple platformer, building a straight path out of many `ColliderShape`s and having a character walk on it doesn't work.

I am assuming that the issue is that the y-coordinate of every `ColliderShape` is not **exactly** the same, because of `f32` inaccuracies. So the character walks along the straight path but bumps into a block that isn't exactly on the same y-coordinate as the one before it.

Example code

```rust
use bevy::prelude::*;
use bevy_rapier2d::prelude::*;

const SCALE: f32 = 16.;
const PLATFORM_Y: f32 = -8.;
const TILES: isize = 100;
const CONTROLLER_JUMP_IMPULSE: f32 = 15.;

fn main() {
let mut app = App::new();
app.add_plugins(DefaultPlugins);
app.add_plugin(RapierRenderPlugin);
app.add_plugin(RapierPhysicsPlugin::::default());
app.add_startup_system(setup)
.add_system(movement);

app.run()
}

#[derive(Component)]
struct Controller;

fn setup(mut commands: Commands, mut rapier_config: ResMut) {
commands
.spawn()
.insert_bundle(OrthographicCameraBundle::new_2d());

rapier_config.scale = SCALE;

commands
.spawn()
.insert_bundle(RigidBodyBundle {
mass_properties: RigidBodyMassPropsFlags::ROTATION_LOCKED.into(),
..Default::default()
})
.insert_bundle(SpriteBundle {
sprite: Sprite {
color: Color::rgb(1., 0., 0.),
custom_size: Some(Vec2::new(1. * SCALE, 2. * SCALE)),
..Default::default()
},
..Default::default()
})
.insert_bundle(ColliderBundle {
shape: ColliderShape::cuboid(0.5, 1.).into(),
..Default::default()
})
.insert(ColliderPositionSync::Discrete).insert(Controller);

for x in -TILES / 2..TILES / 2 {
commands
.spawn()
.insert_bundle(SpriteBundle {
sprite: Sprite {
color: Color::rgb(0., 1., 0.),
custom_size: Some(Vec2::new(1. * SCALE, 1. * SCALE)),
..Default::default()
},
transform: Transform::from_xyz(x as f32 * SCALE, PLATFORM_Y * SCALE, 0.),
..Default::default()
})
.insert_bundle(ColliderBundle {
shape: ColliderShape::cuboid(0.5, 0.5).into(),
position: [x as f32, PLATFORM_Y].into(),
..Default::default()
});
}
}

fn movement(
keyboard_input: Res>,
mut controller: Query<(
&mut RigidBodyForcesComponent,
&mut RigidBodyVelocityComponent,
&RigidBodyMassPropsComponent,
&mut ColliderMaterialComponent,
), With>,
) {
let (mut rb_forces, mut rb_vel, rb_mprops, mut co_material) = controller.single_mut();

if keyboard_input.just_pressed(KeyCode::Space) {
rb_vel.apply_impulse(rb_mprops, Vec2::new(0., CONTROLLER_JUMP_IMPULSE).into());
}

let mut x_axis = 0.;

if keyboard_input.pressed(KeyCode::A) || keyboard_input.pressed(KeyCode::Left) {
x_axis -= 1.;
} else if keyboard_input.pressed(KeyCode::D) || keyboard_input.pressed(KeyCode::Right) {
x_axis += 1.;
}

if x_axis == 0. {
co_material.friction = 2.;
} else {
co_material.friction = 0.;
x_axis *= 25. * rb_mprops.mass();
rb_forces.force.x = x_axis;
}
}
```

Somebody else had this issue before, probably with a better explanation of what the issue is about: https://dev.to/sbelzile/making-games-in-rust-part-7-fixing-the-player-randomly-stuck-issue-3mj5.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.