Version 4.5
Question
Hi! So I’m writing this bit of code that lets the player go pretty much transparent for a full second. Something similar to the dodge mechanic in the Champion Island Google Doodle marathon minigame (kind of obscure reference but it’s the first thing I thought of). Right now, the code waits for the player to hit the space button, then sets off the “roll_time” timer, and at the end of that, the '“roll_cooldown” timer is started–like it shows below:
#All there is in the timer(s) script is just the start command so I decided not to show that and just show the player code here.
func _physics_process(_delta):
#when space is clicked, the first timer starts so that the player only rolls for a short period.
if Input.is_action_just_pressed("roll") and roll_ready == true:
emit_signal("roll_begin")
set_collision_layer_value(5, true)
set_collision_layer_value(1, false)
set_collision_mask_value(2, false)
#when the first timer ends, reset roll and start cooldown
func _on_player_roll_time_timeout() -> void:
print("roll complete")
set_collision_layer_value(5, false)
set_collision_layer_value(1, true)
set_collision_mask_value(2, true)
roll_ready = false
emit_signal("roll_cooldown_begin")
#when cooldown is complete, allow for roll again
func _on_roll_cooldown_timeout() -> void:
print("roll cooldown complete")
roll_ready = true
print(roll_ready)
#This code probably isn't really the most efficient but I made it without a tutorial or anything so I think it's pretty good.
But for some reason it keeps looping. I put the the print commands in there for debugging and making sure it’s working right, and right now–after one click of the space button–they keep showing “roll_cooldown_begun” and “roll_begin” which really shouldn’t be connected at all since they’re a part of their own completely different timers… The player is also unable to roll again after (probably because the “roll_ready” bool isn’t true/the cooldown hasn’t technically ended.
Any tips?
I generally find that ‘is_action_just_released’ is more reliable than ‘is_action_just_pressed’, especially in such a fast-repeated function as ‘physics_process’. It may not be a factor in your issue, but it’s a tip, just the same. Hope it helps.
Are all timers set to one_shot?
No they aren’t. Should they be? I thought that would only make them work once…
If one_shot is false, they will automatically restart whenever they finish. It doesn’t prevent you from manually restarting them.
6 Likes
A couple of things in your code.
First, if you’re going to emit a signal, do this:
roll_begin.emit()
The syntax you are using is pre 4.x and no longer the way to emit signals.
Second, don’t use signals for that.
Third, if your timers are less than 0.5 sec in duration, they are not guaranteed to be accurate. Instead you’ll want to turn them into floats and decrement them by delta every frame.
Fourth, as @hyvernox said, you want them to be one-shot. They can still be used multiple times, they just won’t run constantly. (Which was your original question.)
Fifth, do this instead, and remove the code from your timers, delete the roll_ready variable, and delete the signals:
@onready var roll_timer: Timer = $RollTimer #Change the $ link to whatever you called the node.
@onready var roll_cooldown_timer: Timer = $RollCooldownTimer #Change the $ link to whatever you called the node.
func _physics_process(_delta):
#when space is clicked, the first timer starts so that the player only rolls for a short period.
if Input.is_action_just_pressed("roll") and roll_cooldown_timer.is_stopped() and roll_timer.is_stopped():
roll_timer.start()
set_collision_layer_value(5, true)
set_collision_layer_value(1, false)
set_collision_mask_value(2, false)
#when the first timer ends, reset roll and start cooldown
func _on_player_roll_time_timeout() -> void:
print("roll complete")
set_collision_layer_value(5, false)
set_collision_layer_value(1, true)
set_collision_mask_value(2, true)
roll_cooldown_timer.start()
#YOU CAN DELETE THIS ONCE YOU ARE DONE DEBUGGING
#when cooldown is complete, allow for roll again
func _on_roll_cooldown_timeout() -> void:
print("roll cooldown complete")
1 Like