Ledge Grab System: Part IV
In this part of the ledge grab system we will allow the player to press the E key to climb up from the hanging and continue to move.
We downloaded an animation we liked from Mixamo and made sure the it was an FBX for Unity, made a copy of the animation and Baked Into Pose for all of the Root Transform Positions.
We drag the Climbing animation into the Animator window and we want to create a transition from the Hanging animation to the Climbing animation. We will need to create a new Trigger parameter called ClimbUp, and make sure to include this parameter in the transition conditions.
Lets test it out to see how the transition looks by setting the Trigger using the Animator window. We only want this transition to happen when we are Hanging animation and the user presses the E key. Also, animation ends in a crouching position, which we will fix by transitioning back to the Idle animation.
You can see that when we are in the Hanging animation, we still have the Speed set to 1 and Jumping is True. This could disrupt to transition moving from Hanging to Climbing only.
In the Player script, we just need to make a few modifications by setting the Speed float to 0 and Jumping bool false.
Now, when we trigger the Ledge Grab we are transition to Idle because we set the Jumping bool to false.
In fixing this we just need to add a condition to the Jumping to Idle animation. The condition will be GrabLedge false.
The last thing to ensure we can only transition from Hanging to Climbing is add the GrabLedge condition true along with the ClimbUp trigger.
We have a problem with the Climb animation since it moves the model, but not the Player Controller. This happens when the animation doesn’t control the movement, but the script does. This means we will need to create an animation behavior script that will transition to the Idle animation and move the Play Controller position to the animation position.
Animation Script Setup
Lets create an Animation Behavior script by selecting the Climbing animation, clicking Add Behavior, and creating a new Behavior script called “Climb Up Behavior”.
This creates a different kind of script and we will want to organize it into an Animation Scripts folder.
In the Animation Behavior script, there are a bunch of states already preloaded. We want to uncomment and use the OnStateExit since we want to certain behaviors to happen when the animation exits from playing the Climb animation.
When the player is hanging and wants to climb up they will need to press the “E’ key. Right now, the script has no knowledge of the Player being on the ledge. We will create a bool _onLedge to track this and set it to false at the start.
We know we are on the ledge when the GrabLedge method is called, so this is where we will set the _onLedge true.
In Update, when _onLedge is true, we check for the E key then trigger the Climb Up animation.
Now we will need to get the position we want the Player Controller to snap to.
We duplicate the player, pause when the Climb animation is done, move the clone so the feet match up and take note of the Transform position.
On the Ledge Grab script we are going to create a Vector3 variable that will hold the Idle position we just recorded much like we did with the Hanging position.
Since we serialized this variable we can now input those position values.
In the Player script, lets create a public method that will communicate the position we will need to snap to when the Climb animation is completed.
But, the Ledge is the game object that holds that snapping position so we can create a Ledge variable in the Player class called _currentLedge. This will allow us to get data from the current ledge the player is on and not just one ledge in particular.
When we grab a ledge, we will need to take in a ledge meaning we will create a Ledge parameter called currentLedge. Then, we will set the _currentLedge global variable to the one that is being passed in.
Over on the Ledge script, we will pass in “this”, which is the Ledge game object the Player is currently on.
We still need to communicate the stand position, but we want to keep that variable private, so we will create a public method that will return the value.
Back in the Player script, we set the Player’s position to that Vector3 value that is being returned from the current ledge the player is on. Also, we will need to set grab ledge bool back to false, and enable our Player Controller.
Finally, we are ready to call this Climb Up Complete method but when do we ant to call it? When the animator has exited from the Climb animation. In order to call the method, we need to get a handle on the player and we can access it by going through through the animator, and getting the Player game object via the transform. This is stored in a local variable, player. We complete a null check and call the Climb Up Complete method.
The last thing is create a transition from Climbing back to Idle and set the Transition Duration to 0.
This was a lot, but we have most of the Ledge Grab System working and the next thing we will need to do is make this into a prefab. Until then…Cheers!