I can't get await create_timer to work

Godot Version

4.2.2 on Linux

Question

I’m writing a basic platforming game to learn Godot and gdscript

When the character collects enough items on each level the code jumps to a transition scene before starting the next level. I found this a bit jarring so I tried to introduce a slight wait with create_timer but the code isn’t working…testing code:

if global.coins >= 1:
pause2()
print (“return”)

func pause2():
print (“pause 2 start”)
print(“before_timeout”)
await get_tree().create_timer(1.0).timeout
print(“after_timeout”)

The code doesn’t ever print out “after_timeout” . Any idea what I’ve got wrong?

There are a few things to consider when working with coroutines, and some info that is not mentioned in the original post.

When calling pause2() there could be a need for another instance of the await key word in the call stack.

What is the parent function calling pause2()?

The other thing is that the await keyword does not block the processing thread. It returns to the calling function, saving the remaining code to process after the signal event.

Could it be that once pause2() returns awaiting for the timeout signal that you go to delete the scene with this running script?

1 Like

I forgot to mention “return” prints

The parent function is the coin collection function - after a queue_free() there is an if checking how many coins have been collected.

The point of the await is to let the player play the map for a another second or so, then start the transition to the next scene.

So basically,

queue_free()
If goblin.coin >= 1:
  pause2()
  ...

A queue_free() will happen in the next frame well before that 1 second timeout.

And that await function will not prevent the free from happening.

You need to queue_free() within the function of the await.

Yes this is expected. As await doe not block.

The only thing that will be delayed is the final print statement.

func pause2():
  print (“pause 2 start”)
  print(“before_timeout”)
  await get_tree().create_timer(1.0).timeout # < -- returns immediately back to pause2() call.
  # coroutine starts here after timeout
  print(“after_timeout”) # <-- will print after timeout signal.

Sadly the after_timeout never prints.

I was expecting it to print after one second.

I guess it’s because you delete the node before it finishes?

1 Like

I like how you pretty much guessed my code - here’s the actual coin code:

func _on_body_entered(body):
	print("COIN")
	global.score += 10
	global.coins += 1
	print (global.score)
	print (global.coins)
	queue_free()
	if global.coins == 1:
		pause2()

That could possibly be the case - I’ll remove the queue_free() now and test!

Try this,

if global.coins == 1:
  await pause2()
queue_free()

But this will delay the queue free until after the timeout.

That was the actual issue.

Much thanks, I’ll move the queue_free() to later in the code!

1 Like

I actually moved on from queue_free and changed to $CollisionShape2D.set_deferred(“disabled”,true)

global.score += 10
global.coins += 1
print (global.score)
print (global.coins)
$AnimatedSprite2D.visible = false
$CollisionShape2D.set_deferred("disabled",true)
1 Like