How to make a timer in Godot (count up & down in minutes & seconds)

In Godot by Johnny GossUpdated 1 Comment

Timers are incredibly useful mechanisms in games.

They can be used to create cooldown effects, delay methods from executing immediately, or simply show the player how much time has passed in a game.

So, how do you measure time in Godot?

Godot includes a built-in Timer Node that allows you to specify a wait time which, once it reaches zero, will fire a signal that can be used to trigger other events in the game.

Timer Nodes, however, only count down. This means that to measure time elapsed (such as for a stopwatch, for example) you’ll need to keep track of the amount of time that has passed by adding up the Delta Time every frame and storing it in a variable.

In this article, I’ll show you how to use both Godot’s built-in timer node and how to measure time using variables.

Let’s get started.

What you’ll find on this page

Using the Timer Node in Godot (countdown timer)

The Timer Node is ideal for quickly and easily adding a countdown timer to a scene.

If you select a timer node in the scene tree, you’ll see its properties in the inspector to the right.

the timer node in Godot

  • Process Mode: changes whether the timer is updated during idle time or the physics step.
  • Wait Time: the duration of the timer in seconds.
  • One Shot: if true, the timer repeats until it’s stopped. Otherwise, it will count down from the Wait Time to 0 only once.
  • Autostart: whether the timer will begin counting down as soon as it enters the scene tree and is ready.

If you navigate to the Node tab, you’ll see the available signals the node has.

Signals are emitted when certain conditions are met. For example when a node is renamed, or when it enters the scene tree.

The timer-specific signal timeout() is emitted when time_left reaches 0.

You can connect this signal to methods in a script to run them when the timer depletes.

the timeout signal in Godot's timer node

The timeout signal is emitted when time_left reaches zero and can be used as a trigger for other functions.

It’s important to note that methods connected in this way will only run if the signal passes the same amount of parameters.

This means that if you want to connect the timeout signal to another method, it must accept the same parameters as the timeout signal (which is none).

In the example above, you can tell that the signals don’t pass any parameters because there is nothing between the parentheses () of each signal.

How to delay a method using the timeout signal in Godot

The timeout signal can be used to delay methods in Godot.

Let’s see how this works with a simple scene. We’ll create a scene with a label that will alternate between shown and hidden every two seconds.

Go to Scene > New Scene. Click on 2D Scene. This will add a Node2D as the root of the scene. We use a Node2D because it has 2D transform properties such as position which allows us to move it (and its children) around.

I’m using a 2D Scene for these examples, but timers work in any scene and in any dimension.

Double-click the Node2D to rename it. I named mine TimerExampleA.

Add a label and a timer as children by clicking the plus button and searching for them.

Select the label and add some text in the Text property on the right.

As for the timer, set the Wait Time to 2, and enable Autostart. This will make it so the timer starts counting down from two seconds. I’m leaving One Shot unchecked because I want the timer to repeat so that I can see when the timeout signal is emitted.

Godot timer node settings

The default label doesn’t have a built-in way to toggle its own visibility so I’m going to add this functionality to the label by attaching a script to it.

I renamed the label to CustomLabel and used the Attach Script button. You can always right-click a node to view these options too.

Adding a script will open up the script editor. For this example, I’ve created a simple method to toggle the visibility of the label:

extends Label


func toggle_visibility() -> void:
	visible = not visible

Importantly, I’ve made sure that this method has no parameters so that the timer’s timeout signal can safely connect to it.

Click on the timer in the scene tree and navigate to the Node tab to display the timer’s signals. Double-click on the timeout signal to open the connection dialogue.

Keeping the default name of  _on_Timer_timeout() creates a new method automatically with that name.

This naming convention is useful to keep track of what’s triggering the method but, for this example, I’m going to use the toggle_visibility method we just created.

connecting the timeout signal to a method in Godot

Double click the timeout signal to connect it to another method.

Once connected in this way, there are a few UI elements that can help to keep track of signals within the editor.

First off, the timer has a new signal icon in the scene tree.

signal icon in Godot

The signal icon shows that the timer node is connected to a method.

The signal also lists what Node and methods it’s connected to. You can disconnect signals here too.

Godot Node tab view, signal connections

Helpfully, the signal lists its connections in the node tab.

Finally, you can click this icon in the script editor to see what signals are connected to the method.

Connections to method in Godot

You can also check active connections to methods from the method in script editor

If you press F6 to run the scene, you’ll see the label flash every two seconds.

How to connect the timeout signal via a script in Godot

Connecting signals in this way has its benefits. One of which is that we’re able to easily see what signals are connected to in the editor.

However, it’s also possible to connect and disconnect signals during run-time via scripts.

Here’s how:

As a general rule, parent nodes look after their child nodes so I’m going to use TimerExampleA to manage signals between CustomLabel and Timer.

Here’s how to connect the timeout() signal to the CustomLabel:

extends Node2D

# We cache the children should we need to access them again
onready var timer := $Timer
onready var label := $CustomLabel


func _ready() -> void:
	timer.connect("timeout", label, "toggle_visibility")

The timeout signal is connected as soon as the TimerExampleA node has entered the scene tree and is ready, but you can connect or disconnect signals from anywhere in a script which makes this a powerful tool.

Create a one-shot timer in code ()

It’s also possible to create a one-shot timer on the fly. It begins counting down immediately and frees itself from memory after it emits its timeout signal.

# Creates a one-shot timer that lasts wait_time before emitting the timeout signal
var scene_tree_timer := get_tree().create_timer(wait_time)

By combining it with the built-in yield function, we can delay parts of a method from executing.

For example, to delay the playback of a song until the timeout signal is emitted by the scene tree timer:

func play_song(delay_time: float) -> void:

	yield(get_tree().create_timer(delay_time), "timeout")

	# Play the song after delay_time
	# ...
The built-in yield function is how Godot creates coroutines (more about Yield in Godot).

Typically, this is used when you only need to fire a timer once and you won’t restart it.

Which is helpful, as it cuts out the need for creating a timer node that’ll be redundant after one use.

How to begin a game with a 3, 2, 1 countdown in Godot

Just like in the previous example, where I used a timer node to update a label, it’s possible to give timer nodes extra functionality by adding a script.

Such as using a timer node to count down to the start of a game.

Like before, I’ll be using the timeout signal except I’ll be using it to trigger a custom signal, counted_down, which passes a number along with it to keep track of a count variable.

The counted_down signal can then be used to update a label or to trigger some another function.

extends Timer

signal counted_down(number)

export var _count := 5

The export keyword allows me to change this in the inspector.

Showing the count variable in the inspector

The export keyword is required for the count variable to show in the Inspector.

Connect the timeout signal to the _on_timeout() method in the ready step in the same way as before.

However, rather than connect to another object, this custom timer is connecting to itself.

func _ready() -> void:
	connect("timeout", self, "_on_timeout")


func _on_timeout() -> void:

	emit_signal("counted_down", _count)

	_count -= 1

	if _count < 0:
		stop()

This works because the timer is repeatedly measuring a second. Then when the timer reaches zero, it will emit the counted_down signal to pass along the current count and then reduce the count by 1.

The timer will then stop once the count reaches zero.

How to use a timer node to limit weapon fire in Godot (cooldown timer)

While timers are often used to measure and display time, they are also useful for implementing gameplay mechanics.

Such as for limiting input. For example, you may want to add a cooldown to a weapon or skill so that it can only be re-triggered after a specified delay.

Let’s say that you want to make a laser that can only fire a second time after cooling down for one second.

First, attach a timer as a child.

Next, make sure the timer is set to One Shot.

One Shot timer node setting Godot

We can then use a script to limit input after the laser is fired.

# Laser.gd
extends Node2D

onready var timer := $Timer


func _input(event : InputEvent) -> void:

	if not timer.is_stopped():
		return

	if event is InputEventMouseButton:
		if event.button_index == BUTTON_LEFT and event.pressed:
			fire()


func fire() -> void:
	timer.start()
	print("laser fired")

Every time the player clicks, the Laser fires and starts the timer.
When the _input() function is triggered, it checks to see if the timer is running (or, specifically, if it has not stopped) and, if it is still running, returns to prevent the laser from firing until the timer has stopped.

Using Animation Players as timers in Godot

It’s worth noting that you could also use an Animation Player instead of a timer to limit fire or an action. After all, an animation has a set duration as well which you can tweak in the editor.

extends Node2D

onready var animation_player := $AnimationPlayer


func _input(event : InputEvent) -> void:

	if animation_player.is_playing():
		return

	if event is InputEventMouseButton:
		if event.button_index == BUTTON_LEFT and event.pressed:
			fire()


func fire() -> void:
	animation_player.play("fire")
	print("laser fired")

This could be useful if you want to tie the gameplay to a specific animation. For example, if you want a sword to finish swinging before you can attack again.

How to create a timer in Godot without using the Timer Node

Timer nodes in Godot are great for many things, but they’re no use if you want to keep track of an unspecified amount of time.

For example, if you want to continuously count up, and measure how much time has elapsed, like a stopwatch.

For that, you’ll need to add up time as it passes every frame (using the delta value), storing it in a float variable.

Here’s how…

How to create a stopwatch style timer in Godot (count up)

To create a stopwatch timer, create a new scene with a label and attach a script.

At its simplest, we just need to keep track of one thing: the elapsed time.

extends Label


var time_elapsed := 0.0

To keep track of how much time has elapsed, add the amount of time that the last frame took (the delta value) to the time_elapsed variable every frame using the _process() method.

Like this:

func _process(delta: float) -> void:

	time_elapsed += delta

The delta value allows you to calculate time independently of framerate. So if a frame takes longer to process, because of increased graphics or cpu load for example, the time value is still measured accurately.

This will give you a time value, in seconds, that you can then use in your game.

But how can you display the raw seconds value in a useful format? 

Such as in minutes and seconds, for example?

How to display a time value in Godot in minutes and seconds

If you’re using timers to measure time elapsed or time remaining, you’ll likely want to show the time value in a format that the player is used to. Such as in minutes, seconds and, possibly, milliseconds too.

Godot timer display example

Unless you’re a machine, you’re probably used to seeing time in minutes, seconds and, sometimes, milliseconds.

Here’s how…

First, you’ll need to calculate the minutes, seconds and milliseconds individually.

For this to work, you’ll need a base time value, which needs to be in seconds.

To calculate the minutes, divide time by 60.

var minutes := time / 60

You might have noticed that this integer division returns a float instead of an integer. In this example, we don’t need to use an integer because we can chop off any decimal places when we insert the value into a string.

To get the seconds, you’ll need to get the remainder after dividing by 60 using the built-in fmod function. The fmod function is a modulo function that specifically works with floats.

var seconds := fmod(time, 60)

Modulo is a calculation that returns the remainder of a value after division by another. In this case, we’re using it to get the number of seconds that don’t make up a whole minute.

We’re using the fmod function specifically because we’re working with floats. If we were using integers, we’d use the percent symbol %, which is how modulo typically works, and how it works in other languages:

# Prints 40
print(100 % 60)

To get milliseconds, use the fmod function but, this time, with a divisor of 1. Just like when getting the seconds, this will return a remainder except, in this case, it will be the remaining amount that doesn’t make up a whole second. We’ll chop off any extra digits when we format the string.

var milliseconds := fmod(time, 1) * 100

Next, insert the minutes, seconds and millisecond time values into strings using format specifiers. We’ll use the decimal integral d to insert the decimals we’ve calculated above. We also define the padding as 02 which will make sure the value has two characters. The 0 here makes any padding a “0”.

var time_string := "%02d:%02d:%02d" % [minutes, seconds, milliseconds]

In this example, I’m using the decimal integral d to insert the calculated time values. Defining the padding as 02 will make sure that each value has two digits. The 0 makes any padded value a zero.

Here’s what all of that looks like in a reusable method:

func _format_seconds(time : float, use_milliseconds : bool) -> String:
	var minutes := time / 60
	var seconds := fmod(time, 60)

	if not use_milliseconds:
		return "%02d:%02d" % [minutes, seconds]

	var milliseconds := fmod(time, 1) * 100

	return "%02d:%02d:%02d" % [minutes, seconds, milliseconds]

The method takes the time in seconds and returns a formatted string which can be displayed using a label node.

Note that I added a second boolean parameter called use_milliseconds, which can be used to switch between showing milliseconds or not.

The label’s text can be updated in the _process() method which is called every frame. The _delta parameter is the time in seconds between the current frame and the last frame and will vary depending on the framerate.

extends Label

onready var countdown := $Timer


func _process(_delta : float) -> void:
	text = _format_seconds(countdown.time_left, use_milliseconds)
Godot throws a warning if a parameter isn’t used in the method. To avoid this, I’ve prefixed parameters with an underscore “_” to signal to the editor to ignore them.

Now it’s your turn

How are you using timers in your project?

Are you using the Timer Node, or are you making them via scripting?

Whatever it is let us know by leaving a comment.

Image Attribution

Godot Engine Logo (edited for use on this site) by Andrea Calabró licensed under a Creative Commons Attribution 4.0 International License (CC-BY-4.0 International) https://creativecommons.org/licenses/by/4.0/.

Johnny Goss profile picture

by Johnny Goss

I make tutorials and games using the Godot game engine.

Get Game Development Tips, Straight to Your inbox

Get helpful tips & tricks and master game development basics the easy way, with deep-dive tutorials and guides.

How this content was created

This article was written using first-hand research and experience, without the use of AI. For more information on how Game Dev Beginner articles are written, see my writing policy.

Comments

  1. Aren’t these centiseconds, that you are calculating?`
    Other than that: Thank you! Great help!

Leave a Comment