Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create a timer in Godot?

How do I create a timer in Godot which destroys the script's object after a given amount of time? I am looking to remove bullets from a game after a while to reduce lag.

like image 412
FluffyPancakes1 Avatar asked Dec 20 '25 23:12

FluffyPancakes1


2 Answers

There is a Timer node that you can use. You can add it as a child, set the wait time (in seconds) - you could set it as one shot, and auto start - connect the "timeout" signal to your script, and on the method call queue_free to have the Node (and children, which includes the Timer) freed safely.


You can do that from code too, if that is what you prefer. So, let us go over what I just said, but instead of doing it from the editor, let us see the equivalent code:

Create a Timer, add it as a child:

var timer := Timer.new()
add_child(timer)

Set the wait time (in seconds):

timer.wait_time = 1.0

Set as oneshot:

timer.one_shot = true

Instead of setting it to auto start (which would be timer.autostart = true), let us start it:

timer.start()

Connect the "timeout" signal to a method. In this case, I'll call the method "_on_timer_timeout":

timer.timeout.connect(_on_timer_timeout)

func _on_timer_timeout() -> void:
    pass

Note: it is also possible to the signal by name

timer.connect("timeout", _on_timer_timeout)

func _on_timer_timeout() -> void:
    pass

See also:

  • How to upgrade connect from Godot 3 to Godot 4
  • Connecting a signal via code
  • Signal.connect
  • Object.connect

Then in that method _on_timer_timeout, you can call queue_free:

timer.timeout.connect(_on_timer_timeout)

func _on_timer_timeout() -> void:
    queue_free()
like image 85
Theraot Avatar answered Dec 24 '25 10:12

Theraot


Edit: I stand corrected, the best approach is to use a callback like Theraot's answer says:

func _on_timer_timeout_funcname() -> void:
    # Do stuff here...
    queue_free() # removes this node from scene

var timer := Timer.new()
timer.wait_time = 1.0 # 1 second
timer.one_shot = true # don't loop, run once
timer.autostart = true # start timer when added to a scene
timer.connect("timeout", self, "_on_timer_timeout_funcname")
return add_child(timer)

I'm leaving my answer below here for people who are more comfortable with a sequential approach, but it can be a bit more tricky to deal with.


In Godot 4, there's an easy way to do this:

# Do some action
await get_tree().create_timer(1.0).timeout # waits for 1 second
# Do something afterwards
queue_free() # Deletes this node (self) at the end of the frame

Important: if you do this in the _process() or _physics_process() functions, more timers get created every frame, which causes several runs to occur all at once before then running the following code. To handle this, simply track whether a timed event is happening.

Example in the _process() with simple attack logic:

var attack_started = false;

func _process(delta):
    if attack_started:
        print("Not attacking, attack code running in background")
        return
    else:
        attack_started = true
        prepare_attack()
        await get_tree().create_timer(1.0).timeout # wait for 1 second
        begin_attack()
        attack_started = false

This await keyword works with everything that emits signals, including collision events!

FYI: yield was replaced with await in Godot 4, and await really just waits for a signal/callback to complete:

await object.signal

get_tree().create_timer(5.0) will create a timer that runs for 5 seconds, and then has a timeout callback/signal you can tap into.

like image 42
slay Avatar answered Dec 24 '25 12:12

slay



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!