Day 90 — Creating a Ledge Grab Mechanic
Hey and welcome!
Now that we’re good and familiar with adding in and getting animations to work it’s time to work on a ledge grabbing mechanic by making use of a hanging animation and snapping the character to the ledge based off of a trigger collision.
To start things off head onover to Mixamo and grab the Hanging Idle animation or any similar that you like.
Add that to your project and connect it to the Any State node in your animator controller so that you have something like this:
Create a new trigger parameter called LedgeGrab and set it as the condition for your new transition. Doing this lets us test out the animation while the game is running which is important for the next steps.
With that sorted create a cube object that’s a child of your player object and shape it out to be a narrow rectangle and set is as a trigger collision. This is going to be our ledge checker. Run the game and trigger your hanging idle animation by clicking it in the animator window and then position it so that your character is accurately grabbing onto it:
When you’re happy, take a note of the positional values and then stop the game and add in those values so that they’re remembered the next time you run the game.
Now it’s time to add in the ledge collider itself, find the platform that you want to be able to ledge grab and then create another cube object that’s a child of your ledge and adjust it to a size that works best for you. Don’t forget to add a rigidbody without gravity and make it a trigger collision!
You can remove the mesh renderer for both cubes like I’ve done above when you’re happy with them so that the player can’t see them.
It’s almost time to get into the code needed for this, before that though go ahead and remove the transition from the any state to the ledge grab in the controller and connect a transition from your jump animation to the ledge grab instead. Remove your trigger parameter and turn it into a bool one instead and add this to your condition in your transition when it’s true.
First things first, add in this new method to your Player script:
public void GrabLedge(Vector3 handPos)
{
_controller.enabled = false;
_anim.SetBool("LedgeGrab", true);
transform.position = handPos;
}
This bit of code disables the character controller so that all movement on our player freezes and then here we activate the ledge grab animation and also update the position of the player based on the value of handPos which comes into play later.
Next up, create a Ledge script and attach it to your ledge collider and add in this code to it:
[SerializeField]
private Vector3 _handPos;private void OnTriggerEnter(Collider other)
{
if (other.tag == "Ledge_Grabber")
{
Player playerController = other.transform.parent.GetComponent<Player>(); if (playerController != null)
{
playerController.GrabLedge(_handPos);
}
else
{
Debug.LogError("Can't find Player script");
}
}
}
This is where we’re checking for the actual collision and calling our new method in the Player script while passing through the value of handPos. The handPos value isgoing to be the position of the player while they’re hanging from the edge which is going to take some trial and error and personal preference until you get something you like.
Keep running and pausing the game until you get a position you’re happy with:
The last part is more trial and error, if this is all working perfectly for you already then you don’t need to do anything. If things aren’t looking quite right then you’ll have to look into changing the position of your ledge colliders, changing the gravity or jump height of your character and even tweaking the animation exit time and the further settings you find in the transition until it all comes together and you get something you’re happy with personally:
As always it’s some pretty cool smoke and mirrors we’re doing here, next time we’ll look into implementing a climb up sequence and get things moving.