Hi, I'm trying to toggle camera shake by putting the set_process function whin a custom function. When I call this function in the main script, I use yield to make sure the function starts working. Then I found that my main process still hanging after the signal was emitted. The weird thing is if I put a one-second yield between set_process and emit_signal function, everything working just fine. How do I fix it in the right way?

Main Script:


extends Node

func _ready():
	var ss = SubScript.new()
	add_child(ss)
	
	yield(get_tree().create_timer(1), "timeout")
	ss.send_job()
	
	yield(ss, "start_working")
	print("Start working!")

Sub Script:

extends Node
class_name SubScript

signal start_working

func _ready():
	set_process(false)

func send_job():
	set_process(true)
#	yield(get_tree().create_timer(1), "timeout")
	emit_signal("start_working")
	
func _process(delta):
	#Do Camera Shaking etc.
	pass

Firstly, your code never calls set_process(true) so _process() callback never gets called

Secondly, if there is no yield in send_job() then it emits the "start_working" signal right away, that is - before yield in main node is called. Thus yield in the main node can never catch that signal because it's late to catch it. So it just keeps waiting forever.

This can probably be done in a less convoluted way but to suggest something we'd need to know the exact functionality you want to achieve.

Sorry, I was testing the code and forgot to change the set_process() to true...(so dumb I am).

I create a class call action, each action has signal complete and a function do_action(). There is an array in the main script to store those actions and trigger those actions in a sequence way. The main script will call the do_action() function and start waiting until the complete signal is emitted. There are two kinds of situations, as in the picture below, the one on left has a waiting time and the right one doesn't, the other actions of this type are working fine until I using the set_process function before emitting the signal.

so... I'm a bit confused about the yield and the signal emit time.

Could you achieve the same effect just using Timers? Maybe be a safer way to handle sequences.

@bingrunj said: so... I'm a bit confused about the yield and the signal emit time.

Why do you need the whole yield/signal thing in the second case? Just normally call the function that triggers the shake and let it normally return. If it all happens immediately as is evident from your red and green arrows, why complicate it needlessly?

If you want to understand the problem with your code - follow the flow in the minimal case example:

in foo:

bar.start()  #signal fires while we're here, inside bar.start(), too early for following yield to catch it
yield(bar, "STARTED")  # entering yield too late, signal already happened, we'll wait in vain 

in bar:

func start():
	print("STARTED")
	emit_signal("STARTED")

@cybereality said: Could you achieve the same effect just using Timers? Maybe be a safer way to handle sequences.

Yes, I also have a type of action that wait for a bit time but the problem come from no waiting time, I think I shouldn't using yield at this type like xyz says.

@xyz said:

@bingrunj said: so... I'm a bit confused about the yield and the signal emit time.

Why do you need the whole yield/signal thing in the second case? Just normally call the function that triggers the shake and let it normally return. If it all happens immediately as is evident from your red and green arrows, why complicate it needlessly?

If you want to understand the problem with your code - follow the flow in the minimal case example:

in foo:

bar.start()  #signal fires while we're here, inside bar.start(), too early for following yield to catch it
yield(bar, "STARTED")  # entering yield too late, signal already happened, we'll wait in vain 

in bar:

func start():
	print("STARTED")
	emit_signal("STARTED")

Thank you very much, I think that make sense not using yield at this king of action.

a year later