#Collision in Bevy_rapier
12 messages · Page 1 of 1 (latest)
The slippage is weird indeed! How are you moving your character ? And how big are your colliders ?
The dimensions of the colliders are shown in the video.
The character is moved using this method:
fn player_movement(
mut entity_query: Query<(&mut Transform, &mut EntityBase, &mut Velocity, Entity), With<User>>,
mut move_event: EventWriter<MovementEntity>,
keyboard_input: Res<ButtonInput<KeyCode>>
) {
if entity_query.is_empty() {
return;
}
for (mut _transform, player, mut _vel, entity) in &mut entity_query {
if player.movable {
let mut direction = Vec3::ZERO;
let mut speed_var: f32 = player.speed.0;
if keyboard_input.pressed(KeyCode::ShiftLeft) {
speed_var = player.speed.1;
}
if keyboard_input.pressed(KeyCode::KeyW) {
direction.y += 1.0;
}
if keyboard_input.pressed(KeyCode::KeyS) {
direction.y -= 1.0;
}
if keyboard_input.pressed(KeyCode::KeyA) {
direction.x -= 1.0;
}
if keyboard_input.pressed(KeyCode::KeyD) {
direction.x += 1.0;
}
if direction != Vec3::ZERO {
move_event.send(MovementEntity(entity, direction.normalize(), speed_var));
}
}
}
}
#[derive(Event)]
pub struct MovementEntity(pub Entity, pub Vec3, pub f32);
fn handle_move(
mut query: Query<(
&mut EntityBase,
&mut Transform,
&mut Velocity
)>,
mut event: EventReader<MovementEntity>,
time: Res<Time>
) {
if event.is_empty() {
return;
}
for event in event.read() {
if let Ok((mut entity_base, mut transform, mut _vel)) = query.get_mut(event.0) {
if event.1 != Vec3::ZERO {
transform.translation = transform.translation + time.delta_seconds() * event.2 * event.1;
entity_base.position = Position(transform.translation);
} else {
transform.translation = entity_base.position.0
}
}
}
}
This is noticeable if you move above 120 units, below everything is plus or minus normal
But I'm still worried about falling into the joint of a wall collision
The code for creating a player and a wall
let (texture, atlas) = DirectionAtlas::set_sprite("human", &handle_dir);
let entity = commands.spawn((
EntityBase {
speed: Speed(50., 75., 25.),
health: Health(100.),
position: Position(Vec3::new(64., 64., 0.)),
direction: DirectionState::South,
movable: true,
..default()
},
SpriteSheetBundle {
texture,
atlas,
transform: Transform {
translation: Vec3::new(0.0, 0.0, 0.5),
..default()
},
..default()
},
EntityType::Humonoid(HumonoidType::Human),
EntityNeutrality::Neutral,
Name::new("Player"),
))
.insert(Velocity::zero())
.insert(RigidBody::Dynamic)
.insert(Collider::round_cuboid(2., 2., 0.001))
.insert(LockedAxes::ROTATION_LOCKED)
.id();
let wall = commands
.spawn((
SpriteSheetBundle {
texture: handle.image.clone().unwrap(),
atlas: TextureAtlas {
layout: handle.layout.clone().unwrap(),
index: TestTextureAtlas::get_index("wall", &handle),
},
transform: Transform {
translation: Vec3::new(tiled_pos.x as f32 * 16. + 8., tiled_pos.y as f32 * 16. + 8., 0.8),
..default()
},
..default()
},
RigidBody::Fixed
))
.insert(Collider::cuboid(8., 8.))
.insert(Name::new("Wall"))
.id();
I think your issue is that you have a dynamic rigidbody but you’re setting its position directly, effectively teleporting it and rapier struggles to find its new place.
Possible paths to resolution could be to use forces or use a kinematicrigidbody 🤔
More info there: https://rapier.rs/docs/user_guides/bevy_plugin/rigid_bodies/#rigid-body-type
The real-time simulation of rigid-bodies subjected to forces and contacts is the main feature of a physics engine for
I put KinematicPositionBased and started walking through walls)
Ah yes you’re right, you’d need to reimplement the KinematicCharacterController.. have you looked at it for inspiration ? Personally I would probably use the rigidbody linvel
Maybe it's because of Velocity, for example, bevy_rapier showed a way to move through the linvel installation. But at that time, I did not like this option, it seems, because of the abnormal movement, or because of the difficulty of unifying the movement of the entity. But even here I doubt it in places.
To begin with, I will try to re-realize the movement, but for me it is secondary. I would rather somehow understand how to combine collisions into one, not calculate them separately.