Skip to content

Commit c89a5fb

Browse files
Merge pull request #51904 from nekomatata/move-and-slide-fixes-3d
Port recent move_and_slide fixes to 3D
2 parents ca7f53d + bae0600 commit c89a5fb

File tree

1 file changed

+29
-30
lines changed

1 file changed

+29
-30
lines changed

scene/3d/physics_body_3d.cpp

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,8 +1080,6 @@ void RigidBody3D::_reload_physics_characteristics() {
10801080
#define FLOOR_ANGLE_THRESHOLD 0.01
10811081

10821082
bool CharacterBody3D::move_and_slide() {
1083-
Vector3 body_velocity_normal = linear_velocity.normalized();
1084-
10851083
bool was_on_floor = on_floor;
10861084

10871085
// Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky
@@ -1111,7 +1109,7 @@ bool CharacterBody3D::move_and_slide() {
11111109
floor_normal = Vector3();
11121110
floor_velocity = Vector3();
11131111

1114-
if (current_floor_velocity != Vector3() && on_floor_body.is_valid()) {
1112+
if (!current_floor_velocity.is_equal_approx(Vector3()) && on_floor_body.is_valid()) {
11151113
PhysicsServer3D::MotionResult floor_result;
11161114
Set<RID> exclude;
11171115
exclude.insert(on_floor_body);
@@ -1130,39 +1128,35 @@ bool CharacterBody3D::move_and_slide() {
11301128

11311129
for (int iteration = 0; iteration < max_slides; ++iteration) {
11321130
PhysicsServer3D::MotionResult result;
1133-
bool found_collision = false;
1134-
11351131
bool collided = move_and_collide(motion, result, margin, false, !sliding_enabled);
1136-
if (!collided) {
1137-
motion = Vector3(); //clear because no collision happened and motion completed
1138-
} else {
1139-
found_collision = true;
1140-
1132+
if (collided) {
11411133
motion_results.push_back(result);
11421134
_set_collision_direction(result);
11431135

1144-
if (on_floor && floor_stop_on_slope) {
1145-
if ((body_velocity_normal + up_direction).length() < 0.01) {
1146-
Transform3D gt = get_global_transform();
1147-
if (result.travel.length() > margin) {
1148-
gt.origin -= result.travel.slide(up_direction);
1149-
} else {
1150-
gt.origin -= result.travel;
1151-
}
1152-
set_global_transform(gt);
1153-
linear_velocity = Vector3();
1154-
return true;
1136+
if (on_floor && floor_stop_on_slope && (linear_velocity.normalized() + up_direction).length() < 0.01) {
1137+
Transform3D gt = get_global_transform();
1138+
if (result.travel.length() > margin) {
1139+
gt.origin -= result.travel.slide(up_direction);
1140+
} else {
1141+
gt.origin -= result.travel;
11551142
}
1143+
set_global_transform(gt);
1144+
linear_velocity = Vector3();
1145+
motion = Vector3();
1146+
break;
11561147
}
11571148

1158-
if (sliding_enabled || !on_floor) {
1159-
motion = result.remainder.slide(result.collision_normal);
1160-
linear_velocity = linear_velocity.slide(result.collision_normal);
1149+
if (result.remainder.is_equal_approx(Vector3())) {
1150+
motion = Vector3();
1151+
break;
1152+
}
11611153

1162-
for (int j = 0; j < 3; j++) {
1163-
if (locked_axis & (1 << j)) {
1164-
linear_velocity[j] = 0.0;
1165-
}
1154+
if (sliding_enabled || !on_floor) {
1155+
Vector3 slide_motion = result.remainder.slide(result.collision_normal);
1156+
if (slide_motion.dot(linear_velocity) > 0.0) {
1157+
motion = slide_motion;
1158+
} else {
1159+
motion = Vector3();
11661160
}
11671161
} else {
11681162
motion = result.remainder;
@@ -1171,12 +1165,12 @@ bool CharacterBody3D::move_and_slide() {
11711165

11721166
sliding_enabled = true;
11731167

1174-
if (!found_collision || motion == Vector3()) {
1168+
if (!collided || motion.is_equal_approx(Vector3())) {
11751169
break;
11761170
}
11771171
}
11781172

1179-
if (was_on_floor && snap != Vector3()) {
1173+
if (was_on_floor && !on_floor && !snap.is_equal_approx(Vector3())) {
11801174
// Apply snap.
11811175
Transform3D gt = get_global_transform();
11821176
PhysicsServer3D::MotionResult result;
@@ -1213,6 +1207,11 @@ bool CharacterBody3D::move_and_slide() {
12131207
linear_velocity += current_floor_velocity;
12141208
}
12151209

1210+
// Reset the gravity accumulation when touching the ground.
1211+
if (on_floor && linear_velocity.dot(up_direction) <= 0) {
1212+
linear_velocity = linear_velocity.slide(up_direction);
1213+
}
1214+
12161215
return motion_results.size() > 0;
12171216
}
12181217

0 commit comments

Comments
 (0)