My journey becoming a Unity game developer: 2.5D Infinite Runner-Ledge Grab System-Pt4
Objective: Create a Climbing animation for the Player. Also, make the Player climb up off a ledge, and stand on a certain position on the floor in their Idle animation.
To begin, download a Climbing animation from Mixamo. Drag the Climbing animation into the FBX folder in Assets. Inside the Climbing animation, find the actual animation and duplicate it. Place the duplicate into the Animations folder, with it selected go to the Root Transform Rotation and Position. Turn on the Bake into Pose so that we control the animation’s movement.
Drag the Climbing animation into the Animator, and in Parameters create a new Trigger name Climb Up.
Create a Transition from Hanging Idle to Climbing. In the Inspector, turn off Has Exit Time as we don’t want to wait for the exact time at which the transition can take effect. Set Transition Duration to zero as we want to go from one animation into the other without delay. In Conditions, add Climb Up trigger for the animation to play and the Ledge Grab parameter with it set to True so that the Player is still active on the ledge when climbing up.
Create another Transition from Climbing to Standing Idle. Leave Has Exit Time, Fixed Duration, and Transition Duration activated as we want the animation to play completely when climbing off the ledge to their Idle animation position.
In the Player script under the Grab Ledge() method, we want to turn off the Player animation’s ability to move when hanging on the ledge by using the Animator’s Set Float to set the Speed to zero, and the Set Bool to set Jumping to False.
When we play the game and have the Player jump on the ledge, go over to the Climb Up trigger and turn it on. Watch the Player’s animation climb up the ledge and stand up, but notice that the Player stands in the Idle position where they were hanging at before. This is happening because the Climbing animation is working fine, but the Player’s controller isn’t moving into the new position where the Climbing animation is located.
Back in the Player script, create 2 new variables name onLedge and activeLedge. OnLedge will have a Type Bool and be set to False. ActiveLedge will have the Type Ledge which will be used to indicate if the Player is on a ledge at the moment.
In the Update() function, we will check IF the Player is on the ledge. If the Player is, we will check also IF the ‘E’ key was pressed. If it was, use the Animator’s Set Trigger to activate the Climb Up to Standing Idle animations.
Last, inside the Grab Ledge() method we want to pass in another argument with a Type Ledge name currentLedge. Set the activeLedge variable to equal the currentLedge that the Player is hanging on to.
Jump onto the ledge, then press the ‘E’ key and watch the Player climb up off the ledge and onto the floor. But, notice how the Player is still not staying in its new position. We must change the Player’s controller current position to the new position after climbing up.
Now we set the activeLedge to equal the currentLedge when the Player grabs a ledge. Now we must move the controller using the Ledge script.
In the Ledge script, we will create a new variable Type Game Object name standPos which will represent the position where the Player will be standing. Then, create a method Public Type Game Object name GetStandPos(). Make it return the standPos object the Player will be standing on.
Back in the Player script, we need to create a Public Type Void method name ClimbUpComplete(). This method will set the Player’s controller position to a new position where the Player stands at after climbing up off the ledge.
First thing we need to do is set the Player’s position to equal the active ledge the Player is hanging on. Then using the GetStandPos() method to get the standPos game object from the Ledge script, and use the position of the standPos object.
After setting the Player’s position, use the Animator to Set Bool the Ledge Grab to False as the Player is not hanging on the ledge anymore. Finally, enable the controller by setting it to True to allow the Player to be in control again.
Now for the animation and controller to work together properly, we will use the State Machine Behavior associated with the animation states. Before doing so, we changed the name of the state Climbing to Climb Up just to make this animation state clearer to know. Click on the Climb Up state, then in the Inspector click on Add Behaviour to create a new script. Name the script ClimbUpBehavior() and open the script.
Inside the Climb Up Behavior script, remove the comments placed around the On State Exit() method which will be called on the last update frame when a state machine evaluate this state. Create a variable Type Var name Player which will get the Animator component attached to the Player’s Model child object. Then, check IF the Player isn’t NULL and if the Player is active, use the player variable to get the ClimbUpComplete() method. This will take control from the Animator and give the Player’s controller total control when their Climb Up animation is completed.
In the Hierarchy with the Ledge Checker game object selected, right-click and create a new 3D Cube name StandPosition. Scale the cube to be wide enough for the Player to stand on, and position on the floor right near the ledge where we want the Player to stand up at.
See the Player stand up on the Stand Position object, but with the Player moving quickly down then back up onto the Stand Position object.
To fix this problem, go back into the Animator and click on the Transition between Climb Up and Standing Idle. Leave Has Exit Time turned on, but set Exit Time and Transition Duration to zero. We want the Player to go from the Climb Up animation to the Standing Idle animation right away.
Now the Player will climb up and stand in its Idle animation with the controller in control.
One other thing we can do is place the Ledge Checker object to the opposite side of the platform. Just rotate it 180 degrees along the Y-axis and position it along the floor’s edge.
In the Player script under the Grab Ledge() method, check IF the Player is moving along the Z-axis to the right. If so, take the transform position being used already and place it inside of this condition. Else, IF the Player is moving to the left, use the same transform position but changing the Z-axis value from negative to positive.
Notice the Player’s hands are a distance away from the ledge. Remember that between the assets and camera’s position we may have to manipulate the hanging player to make them look like they’re grabbing the ledge.
We moved the Player’s hands closer to the ledge by changing the Z-axis value to 0.05f which is less than the previous value.
Now the Player is closer to the ledge if needed, just keep in mind the Player’s position according to the final view of the user playing the game.
Final view of the Player hanging and climbing up off the ledge.