This walkthrough covers the concept of wall sliding and wall jumping. When a player is in the air and pressing against a wall, the player's fall speed will slow the player's falling speed and enable jumping.
This tutorial assumes a project that has been created with the platformer wizard options, but this is not a requirement. Wall sliding and jumping can be added to any platformer project.
This walkthrough covers a number of main concepts for wall jumping
Detecting if the user is "pressing" against a wall when in the air
Defining sliding platformer values
Forcing the player to move "outward" on wall jumps
Playing animations when wall jumping
When the player is sliding against a wall, the player's movement is different than when the player is in the air. The most obvious changes are:
The player falls more slowly (max fall speed is reduced)
The player can jump off of the wall
We can create a new set of movement values by copying the existing Air movement values:
Once copied, change the following values:
Movement Type = WallSliding
Jump Speed = 250
Max Falling Speed = 150
Once the WallSliding values have been defined, we need to detect if the player has collided with a solid wall. We can do this by adding the following method to Player.cs which returns whether the player is wall sliding.
The code above assumes that any horizontal reposition on a collision allows wall jumping. You may want to further restrict wall jumping to certain collision types to prevent the player from wall jumping in some situations. For example, you may not want the player to wall jump when sliding against spikes.
To do this, you can check the LastFrameItemsCollidedAgainst or LastFrameObjectsCollidedAgainst to only allow wall jumping if colliding against certain objects. For example, your if statement may be modified as shown in the following code snippet:
The GetIfIsSlidingOnWall can then be used in the CustomActivity to decide whether the player's AirMovement should be WallSliding or Air, as shown in the following code:
Note that this code uses a property IsSlidingOnWall rather than a local variable. Although a property provides no additional benefits on this code, it will be used later when assigning animations.
With this code in place, the player can now slide down walls and jump when sliding.
The implementation above results in the Player being able to jump against walls indefinitely. Many games push the player outward on jumps. Some games such as Mega Man X push the player outward only slightly, allowing the player to climb a wall through wall jumps. Other games such as New Super Mario Bros U Deluxe push the player outward far enough that the player cannot climb up a single wall.
Whether a player can climb a wall depends on the outward XVelocity applied on a jump.
This code adds a handler to when the player jumps. The jump checks if the player is sliding on the wall and if so, pushes the player "outward". Note that the outwardVelocity is defined here in the HandleJumped method, but you may want to put this variable in the Player entity so that it can be tuned without changing code. Also, keep in mind that a smaller outwardVelocity value results in the player being pushed outward less. If the value is small enough then the player will be able to climb the wall through wall jumping. With the values used here, this value is roughly around 30.
We can add sliding animations by checking the IsSlidingOnWall variable either in code or in the Animations tab for the player. If you are already using the Animations UI, then handling the IsSlidingOnWall variable requires no code. To do so:
Select the Player Entity, and select the Entity Input Movement tab
Click on the Animation item
Copy the CharacterFall animation row
Select CharacterWallSlide animation on the new row
Enter IsSlidingOnWall for the Custom Condition on the new row
The player will now play the CharacterWallSlide animations if the IsSlidingOnWall property is set to true. Note that the .achx file contains CharacterWallSlideLeft and CharacterWallSlideRight, but the generated code selects the appropriate one based on which way the player is facing.