Skip to content

Commit d72c48b

Browse files
authored
Scale skin_width by PhysicsLengthUnit (#898)
# Objective The `move_and_slide_2d` example sometimes gets stuck on ramps due to a skin width that is too small. This is because it's not accounting for the scale of the world. ## Solution Scale the `skin_width` by `PhysicsLengthUnit`. This appears to fix the problem. ## Testing Ran the `move_and_slide_2d` example.
1 parent ca51627 commit d72c48b

File tree

1 file changed

+23
-16
lines changed

1 file changed

+23
-16
lines changed

src/character_controller/move_and_slide.rs

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ pub struct MoveAndSlideConfig {
135135
///
136136
/// Increase the value if you notice your character getting stuck in geometry.
137137
/// Decrease it when you notice jittering, especially around V-shaped walls.
138+
///
139+
/// This is implicitly scaled by the [`PhysicsLengthUnit`].
138140
pub skin_width: Scalar,
139141

140142
/// The initial planes to consider for the move and slide algorithm.
@@ -218,6 +220,8 @@ pub struct DepenetrationConfig {
218220
///
219221
/// Increase the value if you notice your character getting stuck in geometry.
220222
/// Decrease it when you notice jittering, especially around V-shaped walls.
223+
///
224+
/// This is implicitly scaled by the [`PhysicsLengthUnit`].
221225
pub skin_width: Scalar,
222226
}
223227

@@ -276,7 +280,8 @@ pub struct MoveAndSlideHitData<'a> {
276280
/// The entity of the collider that was hit by the shape.
277281
pub entity: Entity,
278282

279-
/// The maximum distance that is safe to move in the given direction so that the collider still keeps a distance of `skin_width` to the other colliders.
283+
/// The maximum distance that is safe to move in the given direction so that the collider
284+
/// still keeps a distance of `skin_width` to the other colliders.
280285
///
281286
/// This is `0.0` when any of the following is true:
282287
///
@@ -322,7 +327,8 @@ pub struct MoveHitData {
322327
/// The entity of the collider that was hit by the shape.
323328
pub entity: Entity,
324329

325-
/// The maximum distance that is safe to move in the given direction so that the collider still keeps a distance of `skin_width` to the other colliders.
330+
/// The maximum distance that is safe to move in the given direction so that the collider
331+
/// still keeps a distance of `skin_width` to the other colliders.
326332
///
327333
/// This is `0.0` when any of the following is true:
328334
///
@@ -476,6 +482,7 @@ impl<'w, 's> MoveAndSlide<'w, 's> {
476482
delta_time.as_secs_f64()
477483
}
478484
};
485+
let skin_width = self.length_unit.0 * config.skin_width;
479486

480487
// Initial depenetration pass
481488
let depenetration_offset =
@@ -502,14 +509,9 @@ impl<'w, 's> MoveAndSlide<'w, 's> {
502509
}
503510

504511
// Sweep the shape along the velocity vector.
505-
let Some(sweep_hit) = self.cast_move(
506-
shape,
507-
position,
508-
shape_rotation,
509-
sweep,
510-
config.skin_width,
511-
filter,
512-
) else {
512+
let Some(sweep_hit) =
513+
self.cast_move(shape, position, shape_rotation, sweep, skin_width, filter)
514+
else {
513515
// No collision, move the full distance.
514516
position += sweep;
515517
break;
@@ -530,7 +532,7 @@ impl<'w, 's> MoveAndSlide<'w, 's> {
530532
shape_rotation,
531533
// Use a slightly larger skin width to ensure we catch all contacts for velocity clipping.
532534
// Depenetration still uses just the normal skin width.
533-
config.skin_width * 2.0,
535+
skin_width * 2.0,
534536
filter,
535537
|contact_point, mut normal| {
536538
// Check if this plane is nearly parallel to an existing one.
@@ -774,7 +776,7 @@ impl<'w, 's> MoveAndSlide<'w, 's> {
774776
}
775777

776778
/// Moves a collider so that it no longer intersects any other collider and keeps a minimum distance
777-
/// of [`DepenetrationConfig::skin_width`].
779+
/// of [`DepenetrationConfig::skin_width`] scaled by the [`PhysicsLengthUnit`].
778780
///
779781
/// Depenetration is an iterative process that solves penetrations for all planes, until we either reached
780782
/// [`MoveAndSlideConfig::move_and_slide_iterations`] or the accumulated error is less than [`MoveAndSlideConfig::max_depenetration_error`].
@@ -864,10 +866,13 @@ impl<'w, 's> MoveAndSlide<'w, 's> {
864866
shape,
865867
shape_position,
866868
shape_rotation,
867-
config.skin_width,
869+
self.length_unit.0 * config.skin_width,
868870
filter,
869871
|contact_point, normal| {
870-
intersections.push((normal, contact_point.penetration + config.skin_width));
872+
intersections.push((
873+
normal,
874+
contact_point.penetration + self.length_unit.0 * config.skin_width,
875+
));
871876
true
872877
},
873878
);
@@ -877,8 +882,9 @@ impl<'w, 's> MoveAndSlide<'w, 's> {
877882
/// Manual version of [`MoveAndSlide::depenetrate`].
878883
///
879884
/// Moves a collider so that it no longer intersects any other collider and keeps a minimum distance
880-
/// of [`DepenetrationConfig::skin_width`]. The intersections should be provided as a list of contact plane
881-
/// normals and penetration distances, which can be obtained via [`MoveAndSlide::intersections`].
885+
/// of [`DepenetrationConfig::skin_width`] scaled by the [`PhysicsLengthUnit`]. The intersections
886+
/// should be provided as a list of contact plane normals and penetration distances, which can be obtained
887+
/// via [`MoveAndSlide::intersections`].
882888
///
883889
/// Depenetration is an iterative process that solves penetrations for all planes, until we either reached
884890
/// [`MoveAndSlideConfig::move_and_slide_iterations`] or the accumulated error is less than [`MoveAndSlideConfig::max_depenetration_error`].
@@ -1021,6 +1027,7 @@ impl<'w, 's> MoveAndSlide<'w, 's> {
10211027
let aabb_intersections = self
10221028
.query_pipeline
10231029
.aabb_intersections_with_aabb(expanded_aabb);
1030+
10241031
for intersection_entity in aabb_intersections {
10251032
let Ok((intersection_collider, intersection_pos, intersection_rot, layers)) =
10261033
self.colliders.get(intersection_entity)

0 commit comments

Comments
 (0)