Dashing multiple times in Unity when not intended

Hi there! I am currently making a 2d platformer game and I was trying to implement an ability to dash once in any direction if the play has touched the ground or if they havent used their dash yet. Basically, the player gets the ability to dash if they have touched the ground and it doesnt go away until they use their dash. The problem I am having is that only sometimes does my code work. Sometimes it will dash once into the air like its supposed to, but other times I can get it to dash 2, 3, or even 4 times even if I am not touching the ground if I just spam the dash button (space). Could I get some feedback and help on what might be causing this issue? Also, sorry if my code is ugly/disorganized.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    //All objects used
    private Rigidbody2D rb;
    private BoxCollider2D boxCollider;
    [SerializeField] private LayerMask jumpableGround;
    private SpriteRenderer sprite;
    private Animator anim;

    //Movement variables
    private float dirX = 0f;
    [SerializeField] private float moveSpeed = 12f;
    [SerializeField] private float jumpForce = 2;
    private readonly float jumpStartTime = 0.2f;

    //Dash variables
    private bool canDash = true;
    private bool hasDashed = false;
    private bool isDashing = false;
    private float dashPower = 18f;
    private float dashTime = 0.35f;
    private float dashCooldown = 0.35f;
    private int dashCounter = 1;
    [SerializeField] private TrailRenderer dashTrail;
    private DashDirection dashDirection;

    //Jumping variables
    private float jumpTime;
    private bool isJumping = false;

    //Coyote time variables
    private readonly float coyoteTime = 0.25f;
    private float coyoteTimeCounter;

    //Jump Buffer variables
    private readonly float jumpBufferTime = 0.2f;
    private float jumpBufferCounter;

    private enum MovementState { idle, walking, running, jumping, falling, lightAttack, heavyAttack, damage, death, roll, dash }
    private enum DashDirection { left, right, up, down, upLeft, upRight, downLeft, downRight, none }

    // Start is called before the first frame update
    private void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        boxCollider = GetComponent<BoxCollider2D>();
        sprite = GetComponent<SpriteRenderer>();
        anim = GetComponent<Animator>();
        dashDirection = DashDirection.none;
    }

    // Update is called once per frame
    private void Update()
    {
        /*  ----------  Cancel movement if dashing  ----------  */
        if (isDashing)
        {
            return;
        }

        /*  ----------    Initial Set-Up    ----------  */
        dirX = Input.GetAxisRaw("Horizontal");
        rb.velocity = new Vector2(dirX * moveSpeed, rb.velocity.y);

        if (IsGrounded())
        {
            coyoteTimeCounter = coyoteTime;
        }
        else
        {
            coyoteTimeCounter -= Time.deltaTime;
        }

        if (Input.GetButtonDown("Jump"))
        {
            jumpBufferCounter = jumpBufferTime;
        }
        else
        {
            jumpBufferCounter -= Time.deltaTime;
        }

        if (IsGrounded() || (isJumping && !hasDashed))
        {
            canDash = true;
        }

        /*  ----------    Y-Axis Movement    ----------  */
        if (jumpBufferCounter > 0 && coyoteTimeCounter > 0f)
        {
            isJumping = true;
            jumpTime = jumpStartTime;

            rb.velocity = new Vector2(rb.velocity.x, jumpForce);
            jumpBufferCounter = 0;
        }

        /*  ----------    Variable Jumping    ----------  */
        if (Input.GetButton("Jump") && isJumping)
        {
            if (jumpTime > 0)
            {
                rb.velocity = Vector2.up * 0.9f * jumpForce;
                jumpTime -= Time.deltaTime;
            }
            else
            {
                isJumping = false;
            }
        }

        if (Input.GetButtonUp("Jump"))
        {
            isJumping = false;
            coyoteTimeCounter = 0;
        }

        /*  ----------    Dashing    ----------  */
        if (Input.GetAxisRaw("Horizontal") < 0)
        {
            dashDirection = DashDirection.left;
        }
        else if (Input.GetAxisRaw("Horizontal") > 0)
        {
            dashDirection = DashDirection.right;
        }

        if (Input.GetAxisRaw("Vertical") < 0)
        {
            dashDirection = DashDirection.down;
        }
        else if (Input.GetAxisRaw("Vertical") > 0)
        {
            dashDirection = DashDirection.up;
        }

        if (Input.GetAxisRaw("Horizontal") < 0 && Input.GetAxisRaw("Vertical") < 0)
        {
            dashDirection = DashDirection.downLeft;
        }
        else if (Input.GetAxisRaw("Horizontal") > 0 && Input.GetAxisRaw("Vertical") < 0)
        {
            dashDirection = DashDirection.downRight;
        }

        if (Input.GetAxisRaw("Horizontal") < 0 && Input.GetAxisRaw("Vertical") > 0)
        {
            dashDirection = DashDirection.upLeft;
        }
        else if (Input.GetAxisRaw("Horizontal") > 0 && Input.GetAxisRaw("Vertical") > 0)
        {
            dashDirection = DashDirection.upRight;
        }

        if (Input.GetButtonDown("Dash") && canDash)
        {
            StartCoroutine(Dash(dashDirection));
        }

        //UpdateAnimationState();
    }

    private void UpdateAnimationState()
    {
        MovementState state;

        if (dirX > 0f)
        {
            if (Input.GetButtonDown("Sprint"))
            {
                state = MovementState.running;
                sprite.flipX = false;
            }
            else
            {
                state = MovementState.walking;
                sprite.flipX = false;
            }
        }
        else if (dirX < 0f)
        {
            if (Input.GetButtonDown("Sprint"))
            {
                state = MovementState.running;
                sprite.flipX = true;
            }
            else
            {
                state = MovementState.walking;
                sprite.flipX = true;
            }
        }
        else
        {
            state = MovementState.idle;
        }

        if (rb.velocity.y > 0.1f)
        {
            state = MovementState.jumping;
        }
        else if (rb.velocity.y < -0.1f)
        {
            state = MovementState.falling;
        }
       
        anim.SetInteger("state", (int)state);
    }

    private bool IsGrounded()
    {
        return Physics2D.BoxCast(boxCollider.bounds.center, boxCollider.bounds.size, 0f, Vector2.down, 0.1f, jumpableGround);
    }

    private IEnumerator Dash(DashDirection dD)
    {
        //Make a dash function that allows the player to dash in the direction they are directing their movement
        isDashing = true;
        canDash = false;
        dashTrail.emitting = true;
        hasDashed = true;
        float originalGravity = rb.gravityScale;
        rb.gravityScale = 0f;
        dashCounter = 1;

        if (dD == DashDirection.left)
        {
            rb.velocity = new Vector2(-dashPower, 0f);
        }
        else if (dD == DashDirection.right)
        {
            rb.velocity = new Vector2(dashPower, 0f);
        }
        else if (dD == DashDirection.up)
        {
            rb.velocity = new Vector2(0f, dashPower);
        }
        else if (dD == DashDirection.down)
        {
            rb.velocity = new Vector2(0f, -dashPower);
        }
        else if (dD == DashDirection.upLeft)
        {
            rb.velocity = new Vector2(-dashPower, dashPower);
        }
        else if (dD == DashDirection.upRight)
        {
            rb.velocity = new Vector2(dashPower, dashPower);
        }
        else if (dD == DashDirection.downLeft)
        {
            rb.velocity = new Vector2(-dashPower, -dashPower);
        }
        else if (dD == DashDirection.downRight)
        {
            rb.velocity = new Vector2(dashPower, -dashPower);
        }

        yield return new WaitForSeconds(dashTime);

        isDashing = false;
        dashTrail.emitting = false;
        rb.gravityScale = originalGravity;
        hasDashed = false;

        yield return new WaitForSeconds(dashCooldown);
    }
}

Hi, after looking at my code some more, I added a dash counter that just stops dashing if it has happened more already and you havent touched the ground, and now it works!

1 Like