2d platformer dash not working godot c#

Godot Version

godot 4.2.1 stable-mono win64

Question

I have been working on a small action platformer in godot 4 with c#, and so far all I have put together a very basic platformer controller, and I was wondering how I might go about adding the ability to dash to my script, as whatever I am trying now does not seem to work. Here is the script in question:

 `using Godot;
using System;
public partial class Player : CharacterBody2D
{

	public bool CanDash = true;
	public int dashes = 1;
	public float movementSpeed = 150f;
	public float jumpVelocity = 200f;
	public float CoyoteTime = 0.4f;
	public float CoyoteCount;
	public float gravity = ProjectSettings.GetSetting("physics/2d/default_gravity").AsSingle();
	// Called when the node enters the scene tree for the first time.
	public override void _Ready()
	{
	}

	// Called every frame. 'delta' is the elapsed time since the previous frame.
	public override void _PhysicsProcess(double delta)
	{
		Vector2 velocity = Velocity;
		if(IsOnFloor() == false)
		{
			velocity.Y +=  gravity * (float)delta;
		}
		if(IsOnFloor())
		{
			CoyoteCount = CoyoteTime;
			dashes = 1;
		}else{
			CoyoteCount -= (float)delta;
		}

		velocity.X = 0;
		if(Input.IsActionPressed("Left"))
		{
			velocity.X = Mathf.Lerp(velocity.X, -movementSpeed, 0.8f);
		}else if(Input.IsActionPressed("Right"))
		{
			velocity.X = Mathf.Lerp(velocity.X, movementSpeed, 0.8f);
		}

		if(CoyoteCount > 0 && Input.IsActionJustPressed("Jump"))
		{
			velocity.Y = -jumpVelocity;
			CoyoteCount = 0;
		}
		
		if(Input.IsActionJustReleased("Jump") && velocity.Y < 0)
		{
			velocity.Y = velocity.Y * 0.1f;
		}

		if(CanDash)
		{
			if(Input.IsActionJustPressed("Jump"))
			{
				if(!IsOnFloor())
				{
					if(dashes > 0)
					{
						velocity.X += movementSpeed*10;
						dashes -= 1;
					}
				}
			}
		}

		Velocity = velocity;
		MoveAndSlide();
	}
}`

my dash currntly just adds an arbitrary value to the velocity, but for some reason this has little to no effect on the characters actual movement, besides just snapping them forward a couple pixels. Any help would be greatly apprecieated.

For the time being, it might be easier to ignore delta. If your project is set to 60 fps, _PhysicsProcess() will call give or take 60 times per second.

public override void _PhysicsProcess(double a_delta) {
   // code
}

The only part of my code affected by delta is gravity? I don’t think it has any effect on the dash.

I suspect it’s because you’re setting Velocity.X to 0.

When you dash, it sets Velocity.X to 10 times the movement speed, then you MoveAndSlide exactly once. The very next time _PhysicsProcess gets called, you reset Velocity.X back to 0, and the dash is effectively cancelled.

The way you’re setting up Velocity.X up above is also a bit odd. You’re using Mathf.Lerp to adjust the Velocity.X 80% of the way to the movement speed, but because you reset Velocity.X every time the physics get processed, you never actually reach the full movement speed. You’re also never actually accelerating, which is probably what you meant to do with Mathf.Lerp.

I would suggest changing that to something a bit more like this:

// Make sure to only update the movement speed when not midair dashing.
if (!isCurrentlyDashing) {
    float desiredMovement = Input.GetAxis("Left", "Right") * movementSpeed;
    float newHorizontalMovement = Mathf.MoveToward(Velocity.X, desiredMovement, someAccelerationValue * delta);
    Velocity = Velocity with { X = newHorizontalMovement };
}

Eventually, you’ll probably want to set up a basic state machine to control when you can or can’t dash

just for fun i put this together. left or right arrow key to move. while moving, press space to dash.

gravity disabled because im lazy.

Untitled

using Godot;
using System;
public partial class MyCharacterBody2D:CharacterBody2D {

	const int k_walk = 0;
	const int k_dash_accelerate = 1;
	const int k_dash_decelerate = 2;
	const int k_dash_release_key = 3;

	const float k_normal_speed = 150;
	const float k_dash_speed = k_normal_speed * 3;

	const Key k_dash_key = Key.Space;

	int m_state = k_walk;
	float m_direction = 0;

	float Dash(float a_velocity) {
		switch(m_state) {
			case k_dash_accelerate:
				// accelerate to dash speed

				a_velocity = Mathf.Lerp(Velocity.X, k_dash_speed * m_direction, .5f);

				if(Mathf.Abs(a_velocity) + 1 > k_dash_speed) {

					m_state = k_dash_decelerate;
				}
				break;
			case k_dash_decelerate:

				// decelerate

				a_velocity = Mathf.Lerp(Velocity.X, 0, .1f);

				if(Mathf.Abs(a_velocity) < k_normal_speed) {

					// velocity less than normal speed?
					m_state = k_dash_release_key;
				}
				break;

			case k_dash_release_key:

				// if dash key is held down, player eventually stops
				a_velocity = Mathf.Lerp(Velocity.X, 0, .1f);

				if(false == Input.IsKeyPressed(k_dash_key)) {

					// walk

					m_state = k_walk;
				}
				break;
		}
		return a_velocity;
	}

	float Walk(float a_velocity) {

		// current direction
		if(true == Input.IsKeyPressed(Key.Left)) {
			m_direction = -1;
		}
		else if(true == Input.IsKeyPressed(Key.Right)) {
			m_direction = 1;
		}
		else {
			m_direction = 0;
		}

		if(k_walk != m_direction) {

			// only dash if we have a direction

			if(true == Input.IsKeyPressed(k_dash_key)) {
				m_state = k_dash_accelerate;
				a_velocity = Dash(a_velocity);
			}
			else {
				a_velocity = Mathf.Lerp(Velocity.X, k_normal_speed * m_direction, .1f);
			}
		}
		else {
			a_velocity = Mathf.Lerp(Velocity.X, 0, .05f);
		}
		return a_velocity;
	}

	public override void _PhysicsProcess(double delta) {
		Vector2 v_velocity = Velocity;



		v_velocity.Y = 0; // no gravity. only testing dash




		if(k_walk == m_state) {
			v_velocity.X = Walk(v_velocity.X);
		}
		else {
			v_velocity.X = Dash(v_velocity.X); // all i want for xmas is some shrooms ~/.
		}

		Velocity = v_velocity;
		MoveAndSlide();
	}
}