cooldowns on dashing?

Godot Version

4.4.1

Question

I’m extremely new to Godot and I’m trying to make a dash code, similar to the dash in Cuphead. I want to make a cooldown, but i have no idea where to start. I’ve used other forums and Youtube tutorials, but nothing works and more often then not breaks all of my code.

Hi,

First of all, you will need some is_dashing variable, to know that the player is currently dashing. This variable is set to true on dash start, and to false on cooldown end.


Now, about the actual cooldown, here are two possible solutions:

Use Godot built-in timer

Godot’s Timer node is a good fit for this kind of mechanic. Basically, the idea is that you create a Timer node, you define its duration, and you connect a function to the timer’s timeout signal. Then, on dash start, you start the timer.
You can either create the timer node in your scene and access it in your code, or create it dynamically in code. Since you’re new to Godot, go for the option you’re the most comfortable with.

Use a manual timer

Use a float variable to track the remaining dash time. For instance, say your dash lasts 1 second: on dash start, set the variable value to 1. Then, in _process(delta), decrement the variable by delta; this will make the variable go to zero in one second.
After decrementing, check if the variable is less than 0; if that’s the case, that means the cooldown is over and you can stop your dash.


Both ways have their pros and cons, but to begin with, both are correct, so go for the one you prefer and you understand the most.
Also, I just explained the concepts, you can try implementing them on your own which would be a good way to learn, but of course, let me know if you need a more precise answer :slight_smile:

You can use a variable like Cooldown_Time like this:

Var CooldownTime = 0

func _physics_process():

   if input.is_action_just_Pressed("Your Action") and CooldownTime == 0:
        Dash()
        CooldownTime = 10 #add your own number here to adjust cooldown
   if CooldownTime >= 1:
      CooldownTime -= 1

This just takes the variable, checks it it’s more than zero, and then subtracts it by one every frame.

Hi there,

if CooldownTime >= 1:
    CooldownTime -= 1

You should definitely not do that, as it will subtract one everytime _physics_process() is called, which is a lot of times per frame, and that would make the value independant from the frame rate and hard to control.
Using a timer is fine (I cannot say otherwise as it’s one of the 2 options I’ve proposed already :laughing: ), but it has to be in seconds and handle the frame rate, and use the delta parameter (that, btw, is missing in your _physics_process definition).

2 Likes

What I would personally do in this situation is check whether the cooldown time is over whenever the player tries to dash, for example:

const dash_cooldown_ms := 1000 # 1 second

var last_dash_ms := 0

func _process(delta: float) -> void:
	if Input.is_action_just_pressed(&"dash"):
		_attempt_dash()

func dash_possible() -> bool:
	return Time.get_ticks_msec() - last_dash_ms > dash_cooldown

func _attempt_dash() -> void:
	print("Dash attempted")

	if not dash_possible():
		return

	last_dash_ms = Time.get_ticks_msec()
	print("Dash")

This way you don’t need to constantly change a variable and it just seems much more “robust” to me if the timer is entirely contained inside a function dash_possible (that you could also expand to check for things like whether the player is stunned or something)

If you wouldn’t mind, i would kind of like a precise answer of the manual timer, because I have no idea what “decrementing the variable by delta is”. Neither do i know how to do it.

Sure thing.

To use a timer, declare a float variable, which will be used to count the dash duration in seconds:

var dash_timer: float = 0

Next, add a is_dashing variable, to know if player is currently dashing:

var dash_timer: float = 0
var is_dashing: bool = false

Next, when triggering the dash (wherever you do that, could be for instance in _input or _process), set the variables like this:

is_dashing = true
dash_timer = 1

1 being here the dash duration in seconds, so, change this value to whatever is good for your game’s dash mechanic, it doesn’t have to be 1.


Now that is_dashing is set to true, you have to set it back to false, otherwise the dash will be infinite. To do that, use dash_timer to know how much seconds remain: if the value is >= 0, that means there is some time left, else, that means the dash is over.
If there’s time left, you need to reduce the value over time, otherwise it will always be >= 0.

In _process(delta), you have a parameter called delta that represents the time spent since the last frame. Here’s a link to a more in depth explanation, that’s okay is you don’t get all of the concepts here.
What you need to understand if that, by decrementing a value by delta, you decrement it over time, in seconds, which makes the value act like a timer:

func _process(delta):
    dash_timer -= delta

The last thing we’re missing here is checking if the timer has reached 0, to reset is_dashing to false:

func _process(delta):
    dash_timer -= delta
    if dash_timer < 0:
        is_dashing = false

Then, just use the is_dashing value (true or false) to know if the character is dashing or not, and apply it to anything (collision, speed, particles, whatever you need).

The full code would look something like this:

var dash_timer: float = 0
var is_dashing: bool = false

func _process(delta):
    if Input.is_action_just_pressed("dash"):
        is_dashing = true
        dash_timer = 1

    dash_timer -= delta
    if dash_timer < 0:
        is_dashing = false

Let me know if that helps.

Hm, this seems to not break my half my code or drop the framerate. However, this seems to not let me dash at all. do you have any suggestions of any dash scripts i could use with this timer setup?

Can you share your current code?

sure thing!
i did delete the original dashing code because it wasn’t working the way i intended.


@export var speed = 300
@export var gravity = 30
@export var jump_force = 700
var is_dashing: bool = false
var dash_timer: float = 0

var max_jumps = 2
var jump_count = 0
var cooldowntime = 0
@export var dash_speed = 900

func _physics_process(delta):
   if !is_on_floor():
   	velocity.y += gravity
   	if velocity.y > 1000:
   		velocity.y = 1000
   
   
   
   if is_on_floor():
   	jump_count = 0
   
   
   if Input.is_action_just_pressed("jump") && jump_count < max_jumps:
   	velocity.y = -jump_force
   	jump_count += 1
   	
    
   
   var direction = Input.get_axis("move_left", "move_right")
   
   if Input.is_action_just_pressed("dash") && dash_timer < 0:
   	velocity.x = dash_speed * direction
   
   if Input.is_action_just_pressed("dash"):
   	is_dashing = true
   	dash_timer = 1
   	
   	dash_timer -= delta
   	if dash_timer < 0:
   		is_dashing = false
   
   
   
   velocity.x = speed * direction
   move_and_slide()
   
   
   
   print(velocity)

I’m not sure as the formatting may be wrong, but it seems that the dash_timer decrement is done in that if block:

if Input.is_action_just_pressed("dash"):
   	is_dashing = true
   	dash_timer = 1
   	
   	dash_timer -= delta
   	if dash_timer < 0:
   		is_dashing = false

You don’t want to do that, as it would decrement the value only when pressing the input, which is wrong, you want to do that every frame:

if Input.is_action_just_pressed("dash"):
   	is_dashing = true
   	dash_timer = 1
   	
dash_timer -= delta
if dash_timer < 0:
    is_dashing = false

Then, this part is wrong:

if Input.is_action_just_pressed("dash") && dash_timer < 0:
   	velocity.x = dash_speed * direction

You don’t want to change the velocity based on the dash when pressing the input, you want to do it while the dash is running, which the is_dashing variable is representing:

if is_dashing:
   	velocity.x = dash_speed * direction

That should work better. You’ll also have a problem with direction that can be zero when not pressing any input; meaning that if you release the direction input while dashing, the dash will be running but at zero speed. But that’s another problem not related to the dash cooldown itself.