How to Start a Timer from a Button in Another Scene?

Godot Version

v4.3

Question

Hi, I’m new to Godot. I’m working on a point-and-click cooking game, and I have a ProgressBar that acts as a timer. The timer works fine, but I would like the timer to appear and start when the button is clicked, and when the time runs out the bar disappears. The problem is that the button is in a different scene from the timer.

The button and timer each have their own scene and script and are placed in the main scene.

Current Setup:

  • Bar Timer Scene(Timer): Contains Control, ProgressBar, and Timer.
  • Sausage Scene(Button): Contains Aread2D, CollisionShape2D, Sprite2D and AnimationPlayer.

Button Script:

extends Area2D

@onready var animation_player: AnimationPlayer = $AnimationPlayer


# Play hover button animation
func _on_mouse_entered() -> void:
	animation_player.play("sausage_hover")


# Play idle button animation
func _on_mouse_exited() -> void:
	animation_player.play("sausage_normal")


## Play click button animation
func _on_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if event.is_action_pressed("LMB"):
		animation_player.play("sausage_click")

ProgressBar script:

extends Control


@onready var texture_progress_bar: TextureProgressBar = $TextureProgressBar
@onready var timer: Timer = $Timer
var duration = 20.0


# Initialize the progress bar and timer settings when the scene loads
func _ready():
	texture_progress_bar.max_value = duration
	texture_progress_bar.value = duration
	timer.wait_time = duration
	
	
# Update the progress bar based on the timer's elapsed time
func _process(delta: float) -> void:
	if timer.time_left > 0:
		texture_progress_bar.value = timer.time_left

What’s the best way to start a timer from a button that exists in another scene? Should I use signals, an autoload, or another method?

Any help or examples would be appreciated! Thanks!

If you intend to re-use this “Sausage” button use a signal, otherwise you could get a NodePath/@export to the “Bar Timer” or it’s timer directly.

extends Area2D

@export var timer: Timer

func _on_input_event(viewport: Node, event: InputEvent, shape_idx: int) -> void:
	if event.is_action_pressed("LMB"):
		animation_player.play("sausage_click")
		timer.start()
1 Like

It works using a signal. Tried using node path but always get a ‘null instance’.
Thanks for the solutions!