How to add dash cooldown?

Hello I am trying to add a dash cooldown to my dash script. But there is something I am misunderstanding. How would I go about adding a coroutine to set canDash true after ‘x’ amount of seconds then false after?
I have tried different ways such as setting canDash false at the end of this script, reenabling it with a coroutine but it makes it stop running , I am assuming because it is in update function and because of that the if statement breaks. Please help me understand. <3

private void Update()
{
        if (dash) // gets set to true when shift is clicked
        {
            if (canDash) // used for dashCooldown
            {
            
                dashVelocity = characterDirection * moveSpeed * dashPower;
                controller.Move(dashVelocity * Time.deltaTime);
                StartCoroutine(DashPeriod()); // dash gets set to false after 'x' amount of time
              
            }
        }
}

Cooldown timers, gun bullet intervals, shot spacing, rate of fire:

GunHeat (gunheat) spawning shooting rate of fire:

Hey thanks for your reply! I see how this should work, but for some reason now my player no longer can dash, unless i remove the dashCooldown if condition.
Here is what I added

 public float dashCooldown = 2f;
   private void Update()
    {

    if(dashCooldown > 0)
        {
            Debug.Log(dashCooldown);
            dashCooldown -= Time.deltaTime;
        }
        if (dash)
        {
            if (dashCooldown <= 0)
            {
            
                dashVelocity = characterDirection * moveSpeed * dashPower;
                controller.Move(dashVelocity * Time.deltaTime);   
                StartCoroutine(DashPeriod());
                dashCooldown = 2f; 
           } 
}
        }

The dash cooldown gets reset everytime, but no longer moves the player. What do you think Is wrong?

Absolutely no idea, but here is how you can instantly and trivially find out!

You must find a way to get the information you need in order to reason about what the problem is.

What is often happening in these cases is one of the following:

  • the code you think is executing is not actually executing at all
  • the code is executing far EARLIER or LATER than you think
  • the code is executing far LESS OFTEN than you think
  • the code is executing far MORE OFTEN than you think
  • the code is executing on another GameObject than you think it is
  • you’re getting an error or warning and you haven’t noticed it in the console window

To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run? what order does it run in?
  • what are the values of the variables involved? Are they initialized? Are the values reasonable?
  • are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

Knowing this information will help you reason about the behavior you are seeing.

You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as Debug.Log("Problem!",this);

If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

You could also just display various important quantities in UI Text elements to watch them change as you play the game.

If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: https://discussions.unity.com/t/700551 or this answer for Android: https://discussions.unity.com/t/699654

Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

Here’s an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

https://discussions.unity.com/t/839300/3

When in doubt, print it out!™

The first suspect thing is you have wrapped the Move call inside conditions it probably doesn’t belong inside of.

Now your logic is only moving the player for one single frame, where as before you moved the player over multiple frames.

ah that makes sense! Do you think removing the coroutine and using invoke would help this situation? I’m not quiet sure how to go about it.

No, the problem is that you are not moving the player while the cooldown is in effect because you have a conditional check “if (dashCooldown <= 0)” and that is skipping over the movement code.

You want to change the logic so that the player cannot START dashing if the cooldown is in effect. but still continue to dash if they are already dashing.

1 Like

This ^ ^ ^

The act of “being dashing” should only do things like:

  • increase the the rate of movement
  • perhaps suppress change of direction?
  • perhaps change into the animation for dashing?

The same Move() code should ideally still be called regardless of dash or not.

You want to avoid any and all code duplication.

1 Like

Thank you Kurt and kdgalla for your help.
I simply just moved the dashCooldown conditional into my dash function like you basically said.

Here is the full code:

public class Dash : MonoBehaviour
{
    [SerializeField] CharacterController controller;
    [SerializeField] Movement movement;
    //public Vector2 dashDirection;

    [Header("Dash Settings")]
    public Vector3 dashVelocity;
    private bool dash;
    public float dashPower = 2f;
    public float dashDurationTime = 0.3f;
    public float dashCooldown = 0f;
    public float dashCooldownTimer;

    void Update()
    {
        if (dashCooldown > 0)
        {
            dashCooldown -= Time.deltaTime;
        }

        if (dash)
        {

            dashCooldown = 2f;
            dashVelocity = (transform.right * movement.move.x + transform.forward * movement.move.y) * movement.moveSpeed * dashPower;
            controller.Move(dashVelocity * Time.deltaTime);
            StartCoroutine(DashDuration());

        }
    }

    public void DoDash()
    {
        if (dashCooldown <= 0)
        {
            dash = true;
        }
    }

    public IEnumerator DashDuration()
    {
        yield return new WaitForSeconds(dashDurationTime);
        dash = false;
    }
}