Some signal emissions are dropped, are they supposed to?

Godot Version

4.3

Question

hi so i want to make the player move on a grid, and i wanted it to queue inputs while it’s animating the walking, so that if you quickly press thrice, it walks forward 3 turns, even tho twice you pressed it while it was already walking the first turn.

i tried to do this using a coroutine that waits for a signal that tells it what to do (emitted from _input), does the movement, and then processes the next signal only after the movement animation has completed. however it doesn’t actually work the way i wanted - if i press a key while it’s animating, nothing happens after it finishes. i see the print_debug in _input executes twice, but the one in walk only once. so signal emissions are dropped while no one is waiting for it?

here is the script, it’s for a Node3D but also expects there to be a child node Camera

extends Node3D
enum Movement {FORW, BACK, TURNL, TURNR, STRL, STRR}
signal move(m: Movement)
func _ready() -> void:
	move_loop()
func _input(event: InputEvent) -> void:
	if event.is_action_pressed("ui_up"):
		print_debug("going froward")
		move.emit(Movement.FORW)
	elif event.is_action_pressed("ui_down"):
		move.emit(Movement.BACK)
func move_loop():
	while true:
		var m = await move
		print_debug("moving, ", m)
		match m:
			Movement.FORW: await walk(0, -1)
			Movement.BACK: await walk(0, 1)
var step_size = 0.1
var step_time = 0.04
func walk(dx, dy):
	var d = Vector3(dx, 0, dy).rotated(Vector3(0,1,0), -$Camera.rotation.y)
	var pos0 = position
	var steps = ceil(max(abs(d.x), abs(d.y)) / step_size)
	var step: Vector3 = d / steps
	for _i in range(steps - 1):
		position.x += step.x
		position.z += step.y # z is horizontal cuz we are in 3d
		await get_tree().create_timer(step_time).timeout
	self.position = pos0 + d

(in the end i fixed it in my code by removing the parameter from the signal, using an array as the queue and only using the signal to wake up the coroutine, i should’ve done it that way because i can actually limit the queue, but also i’d like to know, what’s with the signal in the code i sent here, is this a bug in the engine?)

Your execution of code in the move_loop() function awaits completion of the walk() function, which awaits the Timer.timeout signal. During this whole awaiting, your var m = await move is not being called, so the loop is not waiting for this signal. It will listen to it again only after the execution of the walk() is finished.
Nonetheless, I would also go into the route of creating an Array. In general, using while loop for this purpose seems like an overkill to me and might be very error-prone. I would use _process() function and boolean variables to control execution of the code respectively. But that’s a preference in the end, whatever works - works :slight_smile: