Platformer character sliding up slopes instead of jumping

Godot Version

4.2.1

Question

I have a platformer character that is not jumping when moving up steep slopes. This only happens when I move up slopes, not if I’m stationary. I’ve tried a lot of things, but I can’t get it to work. Can someone help?

extends CharacterBody2D
## An node that has all things required for a killable platformer player character.
##
##Very reusable. Allows coyote jump, air jumps, and killing the character.
class_name PlayerCharacter2D
signal kill_me(body,me)## signal that enemies connect to to be notified when somebdy hits my death area.
@export var SPEED:float = 13000.0 ## Player walk speed.
@export var JUMP_VELOCITY:float = -450.0## Jump height.
@export var FALL_MODIFIER:float=100.0##Speed at which you fall, added onto gravity to allow low gravity and etc.
@export var SLOW_DOWN_SPEED:float=1100.0## Speed at which you slow down.
@export var max_jumps:int=1## Max jumps/air jumps allowed.
@export var jumps_allowed:int = 1## Counter that counts how many jumps/air jumps the player has left. Do not change in remote or editor!!
@export var coyote_timer:Timer## Coyote timer.
@export var max_floor_angle:float = 89.0## Max floor angle on which I can walk on.
@export var slide_angle:float = 55.0## Angle at which the floor is a slope.
@export var slide_speed:float=-400.0## Speed at which I slide down slopes.
@export var can_air_jump:bool=true## If I can air jump.
@export var collison_shape:CollisionPolygon2D## My collision shape.
@export var can_coyote = true## If you can coyote jump. Do not change in remote or editor!!
@export var on_jumpable_ground = true## If you are on ground you can jump from. Do not change in remote or editor!!
@export var Animationplayer:AnimationPlayer## For death/spawn animations.
@export var my_detectable_area:Area2D## Death area.
@export var my_spawning_position:Vector2= Vector2(0,0)
@export var my_spawning_scale:Vector2=Vector2(1,1)
var enabled:bool=true## If we run all mechanics that happen when player is alive or enabled.  Do not change in remote or editor!!
var gravity = ProjectSettings.get("physics/2d/default_gravity")## Gravity right now.
#TODO 
#1.-> find out cause of not being able to jump on slopes while moving
func _ready():## enables all and connects functions.
	my_spawning_scale=scale
	my_spawning_position=global_position
	rotation_degrees=0
	set_physics_process(false)
	_respawn()
	await Animationplayer.animation_finished
	set_physics_process(true)
	my_detectable_area.body_entered.connect(_I_got_touched)
	coyote_timer.timeout.connect(_set_coyote_false)
func _physics_process(delta):## does all physics and movement stuff, if enabled.
	if enabled:
		floor_max_angle=deg_to_rad(max_floor_angle)
		_do_all_stuff_you_need_to_do_on_ground(delta)
		_handle_double_jump()
		_handle_jumps(delta)
		_handle_horizontal_movement(delta)
		move_and_slide()
#region movement
func _handle_horizontal_movement(delta):
	var direction = Input.get_axis("Left", "Right")
	if direction:
		velocity.x = direction * (SPEED*delta)
	else:
		velocity.x = move_toward(velocity.x, 0, SLOW_DOWN_SPEED*delta)
func _handle_jumps(delta):## handle jumps
	velocity.y += gravity * delta #apply gravity
	if Input.is_action_just_pressed("Jump"):
		if on_jumpable_ground or (not on_jumpable_ground and can_coyote): 
			velocity.y = JUMP_VELOCITY
			jumps_allowed -= 1
			if FALL_MODIFIER:
				velocity.y +=(gravity+FALL_MODIFIER) * delta
			else:
				velocity.y += gravity * delta
func _handle_double_jump():## handle air-jumps
	if jumps_allowed>0:
		if not (is_on_floor()):
			on_jumpable_ground=true
func _reset_coyote_timer():## sets can_coyote to true
	can_coyote=true
	print('Can coyote now')
func _set_coyote_false():## sets can_coyote to false
	can_coyote=false
	print("Can't coyote now")
func _set_jumps():## resets air_jump amounts
	jumps_allowed=max_jumps
func _do_all_stuff_you_need_to_do_on_ground(delta):## handles sliding, being able to jump,etc.
	if is_on_floor() and rad_to_deg(get_floor_angle())<=slide_angle:
		on_jumpable_ground=true
		_reset_coyote_timer()
		_set_jumps()
	elif is_on_floor() and rad_to_deg(get_floor_angle())>=slide_angle:
		_set_slide_motion(delta)
	elif not is_on_floor():
		on_jumpable_ground=false
		if can_coyote:
			if coyote_timer.is_stopped(): 
				print("Restarting timer")
				coyote_timer.start() 
func _set_slide_motion(delta):## handles sliding
	on_jumpable_ground=true
	_reset_coyote_timer()
	_set_jumps()
	if not Input.is_action_pressed("Jump"):
		velocity.y=slide_speed*delta
#endregion

I have some videos of this. I am jumping when on the slope, not moving up. It accelerates me off when I go off the slope. Since no-one is seeing this post, I hope others will see this now.

As far as I can tell from your code, anytime is_on_floor() returns true, it should be possible to jump, and when it returns false, it should not be possible, unless the player has coyote time or airjumps available.

So: Are we certain that is_on_floor() returns true while standing on a slope? In your video, only the corner of the character is touching the slope - I’m not actually sure whether the character controller thinks it’s grounded in such a case.

If you find out that is_on_floor() is unreliable in that case, then the answer is simple: You’ll need some additional logic for knowing when you’re on a slope, such as raycasts, or checking any collisions found when calling move_and_slide (see the documentation, all the way at the bottom of the page).

If it turns out that is_on_floor() is behaving entirely as you want it to, then it becomes trickier. Your logic for the movement is fairly complex and involves a lot of different variables for tracking the state of the player. It might be helpful to add some UI elements that can constantly show the state of your various boolean variables, so you can see whether they have the correct state when the character is standing on the slope.

To me it looks like it’s working as it should. The character is jumping, but you’re also pressing right so it’s moving / jumping into the slope, making it look like it’s sliding upwards.

edit: You can increase the jump height (to double at least) to test it. That should make it more clear that the jump actually works on the slope.

It does seem like that’s the problem. I don’t know how to fix it though. I like the height my jump is, and I don’t want to increase it. Is there any formula I can use so that it can increase the jump height based on the slope angle or something?

There’s a get_floor_angle that you can probably use to detect if the character is on a slope and change the jump height, but I haven’t used it myself, so don’t know how exactly it works.

I have used it in my script, and I think it works. I used the following code. I don’t know if this would work for other slopes though.

func _match_jump_to_slope(delta):## handles sliding
	var jump_modifier:float = -(abs((original_jump_velocity+(rad_to_deg(get_floor_angle())*18))))
	JUMP_VELOCITY=jump_modifier

I have tested this out more, and I need a better way for this to work. I think I’m on the right track, but I don’t know how to make it better. The problem here is that this makes the jumps too high for higher angles in the slope, and not high enough for lower angled slopes.