Hi all!
I took a little time off for my wedding anniversary, but I'm back now with the much requested ledge climbing tutorial :)
This post is a continuation of the character controller series I've been writing here. Part 1, basic movement, and Part 2, slopes and jumping.
I will continuing this part with the code of part 2.
Get ready for a lot more raycasting.
Code is linked below, and has comments.

Let's start by finding where the walls are.

Send out a short raycast from the player chest, using a layer mask so it won't hit everything.

Here you can see the red raycast turning green when it hits the wall
We need the point where it hits the wall to find the ledge, so store the hit.point of the raycast. The hit.normal will be used to rotate towards the wall.

Ledges next.

To find ledges, I spawn a sphere above the player (How high will depend on your controllers jump height), slightly in front. You can just use an empty gameobject, but I like seeing the shapes, make sure the Collider is turned off though.

From the sphere there is another raycast. When this hits, we have our ledge position by taking the Y of this raycast, and the x and z of the first raycast.

When it hits, the raycast turns from yellow to cyan

When the ledge point is found, check if the player is close enough to grab it, by using Vector3.Distance from the players face. (This distance value should be tweaked for your character and game.). If the ledge is also flat, send through the position to the character movement script via a grabbing function.

Send over the position, and change the movement type.

While the GrabLedge bool is true, move to the right position, we also need to rotate towards the wall using the wall normals,

In the Character Controller script, I've added an enum to switch between movement types (also makes it easily extendable for something like locked-on movement)
To move left and right along a ledge, change the movedirection input to allow for up/down and left/right movement.
And again we rotate towards the wall while climbing, so the orientation stays good.

For this, another set of raycasts is sent out.

Similar to the first Character Controller post, 5 rays from the ledge detector sphere, when they all hit, there is space, when the normal.y is close to 1, it is also flat, so that's where the climb up is safe.

In the Jump input function, add a check for SafeForClimbup, and if the hanging animation is playing, and start the animation

To actually climb up, just lerp the player position to the position of the ledge.


For the option to drop down, add an input check, to cancel the hanging animation with an animation trigger and return to normal movement type.

The script is referring to specific animation names and triggers, so here is a screenshot of the full animator.

Within the hanging state there is a BlendTree over the Velocity variable to move left and right.

All variables (Jumping etc. are all triggers, not bools!)

I recommend checking out Mixamo for (placeholder) animations. I use them quite a bit for Astro Kat, Even though I need to adjust them and eventually replace most, but the quality of these mocap animations is pretty great.
Ones I've used:
- Braced Hang Shimmy
- Hanging Idle
- Braced Hang to Crouch
1. Replace the CharacterMovement Script from the last tutorial.
2. Add the new LedgeDetector Script to the same object.
3. Setup the Animator like under the animator header.
4. Tweak public variables Grabbing Distance and Character Hang Offset
Thanks for reading and have fun!