How to stop the execution of a function when an event occurs?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Traumaticbean

My _ready function looks like:

func _ready():
    while true:
         yield(_execute_state(), "completed")

_execute_state function waits for timers so one average call takes like 3 seconds. It matches the state of the game object to an enum and does some stuff like animating a laser pointed to player, lock target shoot.

But in between all of this the player can fire bullets to the game object, eventually killing it. So, when that happens I want _execute_state to leave everything (firing bullets with delay, moving laser, etc.) and play the die animation instead. But I don’t know how! How to stop a function from executing whatever it is doing?

is _execute_state() on a secondary thread?

Andrea | 2021-03-15 12:00

No, it’s just another function. Will making it a thread help?

Traumaticbean | 2021-03-17 08:21

let me understand better: i suppose that after yield() you let _execute_state() run again (otherwise what would be the sense of placing in a loop?)
if that’s the case it’s not easy to help you without the code/structure, but since it lasts roughly 3 seconds (and you told us it’s because of timers) i guess you have plenty of moments where the engine simply wait for the timers to finish. These are good “idling” moments to check if the game object is dead. Something like:

func _on_Timer_timeout():
 if dead:
   terminate_execute_function()
 else:
   keep_going_with_execute_function()

you can also add a function to take care of what happens mid-time, like

func kill_game_object():
 dead=true
 if not $Timer.is_stopped():
    $Timer.stop
 terminate_execute_function()

terminate_execute_function() will bring _execute_state() to conclusion and return the completed signal to proceed in _ready().

Andrea | 2021-03-17 13:01

That’s a good way too. I will try to implement something similar.

Traumaticbean | 2021-03-18 07:15

:bust_in_silhouette: Reply From: Inces

I don’t know about existence of such a method, we generally project our code beforehand to control its flow. Since death is a priority above any other actions in your code, than You should add appropriate condition in this function like :

If not_dead == true()
do_your_stuff()
else:
justdie()

I tried that too, but it’s difficult because I use so much yield. Results in too much redundancy.

Traumaticbean | 2021-03-17 08:23

I don’t see how yield interrupts changes in code ?
You were trying to do state machine, right? So You specified conditions for each state already, for example : when press space change state from walking to jumping under condition players in on the ground. So just add everywhere conditions for not being dead :). You can use return for this. Return breaks function immadietely, but it has to be called from within this function.

Inces | 2021-03-17 16:05

I will think about that. For now, I added if dead: return statements to avoid situations that the player won’t like (e.g. before firing bullets). And set_visible(false) the lasers. The code is not the most elegant but it works.

Traumaticbean | 2021-03-18 07:14