My current project relies heavily on ledge grabbing, and I am trying to make sure that the player is aways a set distance from ledges they grab. I’m currently taking the collision point and normal of where a raycast coming from the camera hits the wall, and then moving the player to a set distance from that point along the normal. However, this means that if the player approaches the wall at an angle they are moved along the wall, since the collision point is not at the closest point from the wall to the player. You can see this in the following video when I ledge grab at an angle:
How could I go about moving the player straight back as if the wall collision was always at the closest possible point? I believe that I have all of the necessary values, but the math is going completely over my head.
To solve your problem, you have to somehow remove the unwanted lateral offset between the grab position (black circle) and the player’s position (blue circle). You only want to translate your player along the wall’s normal vector - not any others. There are a couple of ways I can think of that would achieve this desired behaviour.
If you wish to solve the problem solely with the data you have on hand, the following solution is the way to go.
To move along the wall’s normal vector – and eliminate the unwanted motion – you can simply project the vector to your target position onto the normal vector.
# Settings
var distance_from_wall: float
# Collision data
var collision_point: Vector3
var normal: Vector3
# This is what you're currently using
var target_position = collision_point + normal * distance_from_wall
var offset = target_position - global_position
# This is the computation of the desired offset
var offset_projected = offset.project(normal)
var final_position = global_position + offset_projected
This should provide you with the behaviour you’re looking for.
Caveats
There are likely some edge cases with this approach which would require additional raycasts; the current system only takes the wall that is hit into account, and it is assumed that the wall is flat and at a 90 degree angle. However, this is an entirely different problem.