Players dash velocity combines with the wall jump velocity, making the player go flying

Godot Version

4.5.1

Question

When the player wall jumps then dashes (or dashes then wall jumps), the velocity from the wall jump and the dash combine, which sends the player flying. I tried adding a max velocity but it didn't work. I'm pretty bad at coding and Godot so any help to fix this would be appreciated. The game is a 2D platformer if that gives any context that will help by the way.

Could you share more of your code, I feel like some extra context is needed.

I’m assuming doWallJump and dashing are variables you created, but what are they exactly?
Also do you have gravity implemented, and how so?

A video to demonstrate the problem would help too here.

Just from what I see here, I can only speculate that your if statement is probably trying to do too much, but again the snippet you shared isn’t enough context to really know.

Here is the full Player script. Forgive any code that isn’t good or written badly / strangely, I’m still learning. As for the video of the bug, unfortunately I can’t upload it because this is a new account, sorry.

extends CharacterBody2D

const SPEED = 200.0
const DASH_SPEED = 600.0
const JUMP_VELOCITY = -320.0

const WALL_SLIDING_SPEED = 2000
const WALL_JUMP_FORCE = 170.0

var doWallJump = false
var lastDirection

var dashing = false
var canDash = true

var allowMovement = true

@onready var height: Label = $Camera2D/Height
@onready var floor_ray_cast_2d: RayCast2D = $FloorRayCast2D

@onready var coyote_timer: Timer = $CoyoteTimer

@onready var jumpSFX: AudioStreamPlayer2D = $Camera2D/Jump
var yVelocityGreaterThanZero = false
@onready var footstepSFX: AudioStreamPlayer2D = $Camera2D/Footstep
var footstepSoundCanPlayOnWall = true
@onready var dashSFX: AudioStreamPlayer2D = $Camera2D/Dash

@onready var game_time: Label = $Camera2D/GameTime
var time = 0
var timer_on = false

func _physics_process(delta: float) → void:
    # Get the input direction and handle the movement/deceleration.
    # As good practice, you should replace UI actions with custom gameplay actions.
    if allowMovement == true:
        if Input.is_action_just_pressed(“dash”) and canDash:
            dashing = true
            canDash = false

		    dashSFX.play()
		
		    $DashTimer.start()
		    $DashAgainTimer.start()
	
	var direction := Input.get_axis("walk_left", "walk_right")
	if direction && not doWallJump && not dashing:
		velocity.x = direction * SPEED
		lastDirection = direction
	elif not doWallJump && not dashing:
		velocity.x = move_toward(velocity.x, 0, SPEED)
	elif lastDirection && dashing:
		velocity.x = lastDirection * DASH_SPEED
		velocity.y = JUMP_VELOCITY / 10
	
	if is_on_wall_only():
		velocity.y = WALL_SLIDING_SPEED * delta
		if footstepSoundCanPlayOnWall == true:
			footstepSoundCanPlayOnWall = false
			footstepSFX.play()
	elif not is_on_floor(): # Add the gravity.
		velocity += get_gravity() * delta
	
	if Input.is_action_just_pressed("jump"):
		if is_on_wall_only():
			velocity.y = JUMP_VELOCITY
			velocity.x = -lastDirection * WALL_JUMP_FORCE
			lastDirection = -lastDirection
			doWallJump = true
			$WallJumpTimer.start()
			jumpSFX.play()
			footstepSoundCanPlayOnWall = true
		elif is_on_floor() or !coyote_timer.is_stopped():
			velocity.y = JUMP_VELOCITY
			jumpSFX.play()
			footstepSoundCanPlayOnWall = true
	
	var was_on_floor = is_on_floor()
	move_and_slide()
	if was_on_floor && !is_on_floor():
		coyote_timer.start()

func _process(delta: float) → void:
    if Input.is_action_just_pressed(“pause”):
        get_tree().quit()

    if velocity.y > 0:
	    yVelocityGreaterThanZero = true
    if is_on_floor() and yVelocityGreaterThanZero == true:
	    footstepSFX.play()
	    yVelocityGreaterThanZero = false

    if floor_ray_cast_2d.is_colliding():
	    var col_point = floor_ray_cast_2d.get_collision_point()
	    var local_col_point = to_local(col_point)
	    var local_col_point_y = local_col_point.floor()
	    var local_col_point_y_toInt = int(local_col_point_y.y)
	    var local_col_point_y_toInt_devided = local_col_point_y_toInt / 15
	
	    height.text = str(local_col_point_y_toInt_devided) + "m"

    if timer_on == false && (Input.is_action_just_pressed("dash") || Input.is_action_just_pressed("jump") || Input.is_action_just_pressed("walk_left") || Input.is_action_just_pressed("walk_right")):
	timer_on = true

    if timer_on:
	    time += delta

    var mils = fmod(time, 1) * 1000
    var secs = fmod(time, 60)
    var mins = fmod(time, 60 * 60) / 60
    var hours = fmod(time, 3600 * 60) / 3600

    var time_passed = "%02d:%02d:%02d:%03d" % [hours, mins, secs, mils]
    game_time.text = time_passed

func _on_wall_jump_timer_timeout() → void:
    doWallJump = false

func _ready() → void:
    add_to_group(“player”)

func _on_dash_timer_timeout() → void:
    dashing = false

func _on_dash_again_timer_timeout() → void:
    canDash = true


Hopefully this is helpful.

Hi, I don’t think your issue is caused by the two velocities combining since you never add or multiply a pre-existing velocity, you only ever assign a new value to it. Can you edit your post so your code has proper formatting (indentation)? I’m not sure where the if-statement blocks end.

I don’t know proper formatting / indentation so I don’t know how to make anything more clear. The two velocities combining was the only thing I could think of as to what the issue was but if it’s not that I don’t even know what’s happening.

Indentation is the blank space before the first character on a line. Make sure that the indentation on the code you posted here matches the one in your script.

Edit:

	if Input.is_action_just_pressed("jump"):
		if is_on_wall_only():
			velocity.y = JUMP_VELOCITY
			velocity.x = -lastDirection * WALL_JUMP_FORCE

I think it might be this code causing the issue? With the values you have set for those constants, your velocity will be Vector2(170.0, -320.0). Is that a value that you are expecting for your game?

Yeah that’s what I expect. Thank you for explaining, I’ll go edit my message to have proper indentation now. If there are any more inconsistencies let me know

I think I found it?

	if is_on_wall_only():
		velocity.y = WALL_SLIDING_SPEED * delta
		if footstepSoundCanPlayOnWall == true:
			footstepSoundCanPlayOnWall = false
			footstepSFX.play()
	elif not is_on_floor(): # Add the gravity.
		velocity += get_gravity() * delta

Your gravity code is applying gravity to all of your velocity when you’re not on the ground, just change it to velocity.y

Let me know if that fixes it.

elif not is_on_floor(): # Add the gravity.

    velocity.y += get_gravity() * delta

I get an error:
Parse Error: Invalid operands “float” and “Vector2” for assignment operator.

by default, the gravity is a vector2 pointing down, so this is probably not the issue.

change also get_gravity().y

I don’t think that is necessary, unless the gravity has been changed from the default to point in a different direction.

No change

Thanks for trying, would it be possible to get a video demonstration of the problem. Visualizing the problem can help a ton. Both the dash into wall jump and vice versa.

It doesn’t let me attach videos because my account is new, sorry

Your code seems fairly straight forward, maybe you should explain what you expect to happen versus what really happens. both parts are important to solving your issue, and we don’t know what you expect to happen. Your WALL_JUMP_FORCE is less than your walking speed and much less than the dashing speed, so I highly doubt the wall jump and dash are adding velocity together, it looks like the dash direction is only flipped.

can you type out a youtube url or the video id?