First, go to Mixamo.com and find an animation of your desire to use as the ledge grab animation. In the game, I will be using “Hanging Idle”. Again, set it to Humanoid and Duplicate the animation clip to manipulate within the project. Since there was no “In Place” check box provided, make sure to bake it into pose.
Well, this is really funny. I have actually never thought about how did they really gave the illusion of hanging in the games I have played. Look what happens if you manually enable ledge grab animation and walk:
Expectedly, we fall down. The idea here is to zero out the gravity as long as we are grabbing the ledge. Expectedly, we will use a collider system to detect if the player is in place for the ledge grab animation and change the gravity accordingly.
First, we need a collider on the player to check if we collided with an object which is suitable for ledge grab. Create a cube as a child object for the player, resize it and then arrange it’s position that will actually look like we are holding it.
Basicly repeat the same on the side that we want our player to grab on to.
So, once the grab checker on the Player and the ledge checker on the surface that we want the player hang on collides, we will create the grabbing illusion. Make sure to turn the Mesh Renderers off on these components and set them to Trigger.
So it is easy to detect the collision between these two, but how are we going to zero the gravity? An option might me turning the Rigidbody component off, but since we are using a Character Controller, there’s no Rigidbody attached to the player. Likewise, turning the Character Controller component off and on will create the same effect. Thus, the idea is to turn the it off once we want the gravity to be 0.
For the cube as the child object of the player, I have created a new Tag as GrabCheck and tagged it. To handle the behaviour on the jump, create a new script for the cube on the edge that we want the player to climb on.
As we will be manipulating many components of the Player with this trigger, it is better to create a new method within the player that will be called once the ledge grab is triggerred.
Here’s the result after a few adjustments for a beteer look:
Now, here comes the tricky part. Once we play the climbing animation, the animation takes the player from a hanging position to a position which is on the platform. Whereas, the actual game object position remains hanging.
This needs to be fixed. We need to simply say to the game to adjust the position of the player once the climbing up animation is over. I was actually unclear regarding deciding on to call the new position within a script or from the inspector, but doing it from the inspector makes more sense as there are more ledges to climb on. From the inspector, we can easily define different Vector3 variables for each ledge.
So how will we tell the player to move to a new position once the climb anim ends? Well, a new thing for me again. I did not know that we can create scripts for animation states. The animation scripts are a little different than the normal scripts. Click on the state that you want to add a behaviour, and click on “Add Behaviour”.
First of all, they inherit from StateMachineBehaviour. These scripts come in with some ready to use methods, that we can use just by deleting the comment chars. As we need to access the player to manipulate its position, we can reach it by reaching its animator component.
Simply, create a bool variable for detecting ledge grab and cache the ledge game object that we are grabbed. Once it is detected, by calling the LedgeGrab method from the Ledge script, we actually make the Player know about which Ledge we are grabbing.
We want the player to climb up once we hit on ‘E’. So the Player script is as below:
Lastly, make sure that animation state changes to “Idle” once the Climb Up finishes.
And here’s the result: