Walljumping on steep slopes

Godot Version

4.2.1

Question

So I decided to test out slopes while making basic movement for my game. I used the build in engine with the character body 2D and I added a walljump mechanic.

var direction = Input.get_axis("Move left", "Move right")

if Input.is_action_pressed("Move up"):
      if falling < 5:
            velocity.y = JUMP_VELOCITY
      elif is_on_wall() and abs(direction) > 0:
            velocity.y = JUMP_VELOCITY
            velocity.x = (0 - direction) * 500

This works really well, unless you go onto a slope that’s too steep to go up, then you can walljump up it. How do I prevent this?

You could get the Dot product of the wall Normal and UP Vector.
pseudo code:

var dot = wall_normal.dot(Vector2.UP)
if dot == 0: # dot product is 0 when the Normal is perpendicular to UP Vector
  #do thing

note: (for normalized vectors, magnitude 1) dot product indicates how much the 2 vectors are aligned, so a dot product of 1 means they point in the same direction, and -1 if they point in opposite directions, 0 would mean they are perpendicular

also: to get the “wall_normal” you can use raycasting, either a raycast2d object or just a raycast
for raycast2d you can use .get_collision_normal() method and for raycast .normal property

1 Like

I tried to implement this system, but now the player won’t walljump at all.

if Input.is_action_pressed("Move up"):
      var wall_normal = $"Player slope check".get_collision_normal()
      var dot = wall_normal.dot(Vector2.UP)
      if falling < 5:
            velocity.y = JUMP_VELOCITY 
      elif is_on_wall() and abs(direction) > 0 and dot == 0
            velocity.y = JUMP_VELOCITY 
            velocity.x = (0 - direction) * 500

Player slope check is the raycast 2D

Are you getting an error/crash?

Also it seems ur missing a “:” at the end here

I think this could work

if Input.is_action_pressed("Move up"):
      
      if falling < 5:
            velocity.y = JUMP_VELOCITY 
      elif is_on_wall() and abs(direction) > 0:
            var wall_normal = $"Player slope check".get_collision_normal()
            var dot = wall_normal.dot(Vector2.UP)
            if abs(dot) < 0.1:
                    velocity.y = JUMP_VELOCITY 
                    velocity.x = (0 - direction) * 500

edit: just realised problem could be that dot isn’t exactly 0(because of inaccuracy) so it isn’t executing the code
thats why the “if abs(dot) < 0.1:” is there, its has a tolerance of 0.1, you should probably tune it tho

1 Like

I’m not getting an error, and the reason that I didn’t use a colon there is because I have to copy the code from my laptop to my phone and just forgot to type it in. I did that code and it still didn’t work, I printed the dot variable to the console and found that it’s always equal to 1.

Oh, i think 2d games use up vector of (0, -1)
Try changing the Vector2.UP to Vector2.DOWN

wait im an idiot nvm → Vector2.UP is (0, -1)

Could you post a screenshot of the scene
-also a screenshot of the raycast touching a slope + console typing out dot=1

Dot of 1 means that the normal of the surface ur raycast is hitting is pointing the same direction as the up vector, which could only be level ground

btw why dont you just use the desktop version of godot forums, im guessing u were away from keyboard?

1 Like

Not sure I can reply with a picture of my scene, I don’t see an option for it. Maybe my trust level isn’t high enough yet? However, I did find something when entering my scene. The target position of my raycast was wrong, so I set it to be on the edge of my players hitbox, but now the player will walljump on the steep slopes again.

Also, I have to do this on my phone because the forums are blocked on my laptop, but not on my phone.

there should be an upload button on the bottom right

also not sure what u mean by blocked on ur laptop, unless it’s a school laptop or something

your scene should look something like this

and the normal like this

so in essence make the player not jump when the normal is pointing away from UP(when they are off ground)

Edit: you could avoid this whole issue by using raycasts to check if player is touching a wall instead of the built-in “is_on_wall()” function

also i really have to go sleep i can reply when i wake up lol

1 Like

This seems to be working well now.


The only remaining problem is that the player will walljump when the slope is below where the raycast is, but I think I can try to fix that on my own, and for some reason, I can’t walljump on a left wall until I walljump on a right wall.

And yeah, it’s a school laptop.

Edit: fixed the first issue, but now the player can’t walljump on left walls at all.

1 Like

U might wanna add a 2nd raycast for the left side

And then before getting the normal, you check which of the 2 raycasts is colliding and run the get_collision_normal() on that raycast

1 Like

I just figured out a different solution, I just set the rotation of the raycast based on the direction. Thanks for your help!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.