Having trouble stopping a timer between consecutive function calls

Godot Version

4.2.1

Question

In my game, I have an interaction system which calls the function LabelInteraction() every time the player interacts with something. Visually, this shows a label that progressively appears thanks to a tween and then, after a SceneTreeTimer times out, the label disappears. The issue I’m encountering is that if the function is called when the timer from a previous call hasn’t finished, the new text disappears (HideLabel is called) before, as it’s using the timer from before. How can I fix this and use a new timer for every interaction, basically ignoring what the previous function’s timer value was?

Here’s the code

extends CanvasLayer


var timer
# Called when the node enters the scene tree for the first time.
func _ready():
	$Label.visible_ratio = 0
	LabelInteraction("This is a test ight but just a bit longer just in case")


func ShowLabel(label):
	var tween := create_tween()
	$Label.text = label
	tween.tween_property($Label, "visible_ratio", 1.0, 0.5).from(0.0) #So it always plays the tween from the start
	
func HideLabel():
	var tween := create_tween()
	tween.tween_property($Label, "visible_ratio", 0.0, 0.5)
	
	
func LabelInteraction(label): 
	#Calculate time depending on string size
	var words = label.split(" ") #Splits all the words in the string
	var time = 2.5 * (words.size()*0.2) #Default time
	
	if timer != null:
		timer.time_left = 0
	timer = get_tree().create_timer(time)
	
	#Label
	ShowLabel(label)
	await timer.timeout #Waits for the timer to emit the timeout signal before executing hide label
	
	HideLabel()
	


i see you are using timer to hide label after some time based on the words
so rather than do use timer, you can just use tween interval then tween property again to hide the label in ShowLabel

func ShowLabel(label,time_delay):
	var tween := create_tween()
	$Label.text = label
	tween.tween_property($Label, "visible_ratio", 1.0, 0.5).from(0.0) #So it always plays the tween from the start
	tween.tween_interval(time_delay)
	tween.tween_property($Label, "visible_ratio", 0.0, 0.5)

func LabelInteraction(label): 
	#Calculate time depending on string size
	var words = label.split(" ") #Splits all the words in the string
	var time = 2.5 * (words.size()*0.2) #Default time
	
	#Label
	ShowLabel(label,time)

or if you insist to keep using the HideLabel function

func ShowLabel(label,time_delay):
	var tween := create_tween()
	$Label.text = label
	tween.tween_property($Label, "visible_ratio", 1.0, 0.5).from(0.0) #So it always plays the tween from the start
	tween.tween_interval(time_delay)
	tween.tween_callback(HideLabel)

func LabelInteraction(label): 
	#Calculate time depending on string size
	var words = label.split(" ") #Splits all the words in the string
	var time = 2.5 * (words.size()*0.2) #Default time
	
	#Label
	ShowLabel(label,time)

While your interpretation is correct, neither of the approaches you mentioned worked. To illustrate it better, here’s a video of the issue

As the video shows, the second label disappears way quicker than it should be, as it’s using the timer from the first interaction (both labels for each of the interactions last around 7 seconds). And then, when interacting again, the new label still disappears early because it’s using the timer it had from the previous interaction. What’s wrong with the code that’s causing the game to use the previous timer?

what’s the expected interaction will happen to the label?
if you interact it first, it will show to full, but when you interact it second time while it’s full, what will happen?

so instead of creating new tween every time ShowLabel is called, use a universal tween so you can reset(kill) it for each new ShowLabel

var tween:Tween
func ShowLabel(label,time_delay):
	if tween:
		tween.kill()
	tween=create_tween().bind_node(self)
	$Label.text = label
	tween.tween_property($Label, "visible_ratio", 1.0, 0.5).from(0.0) #So it always plays the tween from the start
	tween.tween_interval(time_delay)
	tween.tween_property($Label, "visible_ratio", 0.0, 0.5)

func LabelInteraction(label): 
	#Calculate time depending on string size
	var words = label.split(" ") #Splits all the words in the string
	var time = 2.5 * (words.size()*0.2) #Default time
	
	#Label
	ShowLabel(label,time)
1 Like

Yeah that worked perfectly, thank you so much

To clarify the overall idea, the main problem was that the labels (which have a specific time assigned to them based on the words), were on-screen for a shorter or longer time depending on whether the function was already executing or not, and the expected result was that, independently of the function calls, each interaction and the label that comes with it had to be on-screen for a specific period of time

1 Like