Godot Version
4.4.1.stable
Question
I’m currently working on a 2.5D top-down character controller; it involves implementing a custom version of move_and_slide
as part of it that snaps to the 2D gameplay plane as best as it could, so I’m referencing the official implementation of move_and_slide
to ensure I don’t miss any edge cases along the way. It’s generally pretty well documented, but I’m having trouble understanding why reaction to the first collision is handled differently:
if (first_slide) {
Vector3 motion_slide_norm = result.remainder.slide(wall_normal).normalized();
motion = motion_slide_norm * (motion.length() - result.travel.length());
} else {
motion = result.remainder.slide(wall_normal);
}
Okay, so normally you project remaining motion onto the wall you’ve collided with. Makes sense. However, for the first collision remaining motion’s magnitude is calculated as motion.length() - result.travel.length()
rather than the more obvious result.remainder.length()
. I’m having trouble understanding why it does what it does:
First, vector’s magnitude is set to motion.length() - result.travel.length()
instead of result.remainder.length()
- my best guess is that it has something to do with the case of recovering from already being inside of an object. Am I correct?
Second, it applies magnitude to the vector after doing projection, which means motion magnitude is fully preserved and not projected. This part seems like a bug to me, with the correct implementation being
if (first_slide) {
real_t remainder_magnitude = motion.length() - result.travel.length();
Vector3 remainder_adjusted = result.remainder.normalized() * remainder_magnitude
motion = remainder_adjusted.slide(wall_normal);
} else {
motion = result.remainder.slide(wall_normal);
}
It looks like the current implementation would cause issues like CharacterBody2D (only in Floating Motion Mode) accelerated by slides · Issue #101052 · godotengine/godot · GitHub - although that one is 2D, the underlying calculation is identical.