Climbing Ladders in Unity 3D
Yet another way to gain elevation
I’ve got one more locomotion challenge for my 2.5D platformer prototype: ladders. This will involve quite a bit of fiddling, because I’m using found assets that aren’t made with the same scales in mind. Trying to get a ladder animation to fit the rungs of a ladder takes persistence and patience.
But before that, we gotta get the thing working to some degree.
The first objective list is:
- Give the player and the ladder both an idea of what it means to be on or off a ladder
- Get the player on the ladder with a keypress.
- Disable the normal movement when on the ladder
- Enable vertical movement when on the ladder.
- Stop the player at the top of the ladder.
Last things first, I’ll put a 3D primitive box at the top of the ladder with a box collider. Later we’ll change it to a trigger, but for now I just want to avoid climbing off into the clouds when we enable vertical movement.
Get On With It
Now, let’s tell the ladder and the player what they can do with each other. Add a new trigger box collider to the ladder and extend it over the space where the player will climb up the ladder. Also put a rigidbody component on here and turn off gravity.
Create a new Ladder C# script with an OnTriggerEnter() method and an Update() method. We’ll prepare the OnTriggerEnter() thusly:
If trigger is entered by player and if the player is not already on a ladder
…then the playerpresent is true
And the Update():
If the player is present and the E key is pressed
…run the player’s OnLadder() method, telling it a spot near the base of the ladder and which ladder instance this is
…set playerpresent to false
The spot passed through the OnLadder method is an empty transform at the base of the ladder. It must be placed where the player’s hands and feet rest on the ladder rungs while idle (more on fitting the ladder below).
At the end, we’re setting player present to false because while the player is technically still present, they will at that point be stuck to the ladder and we don’t want them pressing the E key and running the OnLadder() method more than once.
Speaking of the OnLadder() method, over in the Player class:
Move the player to the spot indicated
Trigger the ladder climb idle animation
Set animator Speed float to 0 to prevent animation canceling
Set onladder to true
Save a reference to the ladder instance for later
Once onLadder is true, the player’s CalculateMovement() method will take over:
If onladder is true
…get vertical input
…set direction based on vertical input
…trigger the climbing animation
…set velocity to direction * climb speed
From there the normal Character Controller movement scenario plays out as scripted, using the velocity to determine player movement — in this case, only up or down.
Lining Up Limb and Ladder
So, if we run this as we have it, here’s how it looks.
At this camera angle, it’s actually hard to see that the hands are not on the rungs, but…
Yeah, not quite. I do want these to line up, even though it’s not visible in the current iteration of the game. You never know what might happen to camera angles down the pipeline. So let’s fiddle with this.
The idea is to get the ladder to a y-axis scale that the hands and feet are reasonable close to the rungs. Play around with large increments at first, and then smaller increments, until eventually…
That’s more like it.
Now, let’s get off this thing.
Exiting the Ladder
At this point, we’ll need to pull some more animation shenanigans. This process is very similar to the cliff grab climb up, so I won’t quote the full pseudo code in this section — see the previous article if you want more info.
Like the cliff grab climb up, our exit ladder animation moves the model body, but leaves the Player transform where it is. We’ll need to designate a spot to move the Player to at the top using an empty game object. We’ll also need to add a behavior script to trigger at the end of the exit ladder animation that tells the Player when to do all the teleporting and such.
First, that box at the top of the ladder needs to become a trigger. It will get its own C# script: LadderExit. Inside, just a simple block of code detecting the player and signaling the player to exit the ladder using its ExitLadder() method.
The ExitLadder() method just tells the Player that it is time to exit the ladder by flipping a bool toggle.
In the CalculateMovement() method we’ll add some logic so that when _exitLadder becomes true we perform the necessary actions immediately: namely, disabling movement and running the animation.
The Ladder Exit animation plays, and then when it is complete we tell the player the animation is done using an animation behavior script:
And then we move along to our LadderExitComplete() method:
Here we’re just undoing all of the various toggles that put our player in the exit ladder state. We’ll call for the active ladder we stored earlier to tell us where to land. That reaches into the Ladder class:
And, of course, _endPos is serialized and defined in the Inspector.
Now, let’s see the full climb:
Oh, and for fun, here’s an early gif from when I’d forgotten to exclude the rotation based on movement direction:
Okay, that wraps up this article. Tomorrow we’ll do a progress report for wrapping up this project.