Day 82 — Creating Wall Jumping Behaviour in Unity

Connor Fullarton
3 min readJun 5, 2021

--

Hey and welcome!

Next up we’re going to be implementing how to make the player jump between walls in order to get to an area out of reach otherwise. It will work pretty similar to something you’d see in the 3D Super Mario games or in Super Meat Boy.

The little patch of wall up above is going to be our target. In order to jump between the walls we’re going to make use of something called surface normals. Basically, a surface normal is going to provide our character with a direction to jump off of that’s perpendicular to the surface they’re on.

private void OnControllerColliderHit(ControllerColliderHit hit)
{
Debug.DrawRay(hit.point, hit.normal, Color.blue);
}

If you add the above code into the Player script you can see an example of this in action. The OnControllerColliderHit method runs whenever our character controller collides with anything, then we create a ray from the point of impact with hit.point and then we specify the direction the line draws towards with hit.normal.

If you look at the above gif closely you can see this in action, there’s a vertical line coming from the floor since we’re colliding with it and then when we collide with the wall you’ll see a horizontal line, both of these lines are perpendicular to the surfaces they are colliding with.

We can use this information to effectively treat the wall like it’s the floor and provide the logic in our script to jump off of it as we would the floor. There’s a few changes that need to be done and added to the Player script which I’ve highlighted in bold below.

private bool _canWallJump = false;
private Vector3 _wallSurfaceNormal;
private Vector3 _velocity, _direction;
void Update()
{
float horizontalInput = Input.GetAxis("Horizontal");
if (_controller.isGrounded == true)
{
_direction = new Vector3(horizontalInput, 0, 0);
_velocity = _direction * _speed;

if (Input.GetKeyDown(KeyCode.Space))
{
_yVelocity = _jumpHeight;
_canDoubleJump = true;
}
}
else
{
if (Input.GetKeyDown(KeyCode.Space) && _canWallJump == false)
{
if (_canDoubleJump == true)
{
_yVelocity += _jumpHeight;
_canDoubleJump = false;
}
}
if (Input.GetKeyDown(KeyCode.Space) && _canWallJump == true)
{
_canDoubleJump = false;

_yVelocity = _jumpHeight;
_velocity = _wallSurfaceNormal * _speed;
}
_yVelocity -= _gravity;
}
_velocity.y = _yVelocity;
_controller.Move(velocity * Time.deltaTime);
}
private void OnControllerColliderHit(ControllerColliderHit hit)
{
if (_controller.isGrounded == false && hit.transform.tag == "Wall")
{
_wallSurfaceNormal = hit.normal;
_canWallJump = true;
}
else
{
_canWallJump = false;
}
}

To start off with you’ll notice that we’re now declaring global variables for _velocity and _direction and that we’ve put them within the _isGrounded == true if statement. By doing this we’ll now no longer be able to change direction while mid air. This is where we’re making the full use of surface normals since we assign our velocity to the normal which propels the character off of the wall so that we can bounce between the walls. We also assign the jump height to the yvelocity in order to get a bit more height out of the jumps off the wall as well.

The second thing you’ll notice is that there’s a _canWallJump variable which lets the player perform a wall jump if it’s their first jump and also stops them from doing a double jump since that would get in the way with our wall jumping.

With all that done you should have something like the above working for you!

--

--

Connor Fullarton
Connor Fullarton

Written by Connor Fullarton

Hey and welcome! My name is Connor and my goal here is to put out a daily post for a full year about my game development journey.

Responses (1)