+5 votes

I want to know if there is a way to use yield() to wait a function to end its execution and then resume the code from where it was called. Cause in the code below, if I comment the yield(get_tree().create_timer(.5), "timeout") line the queuefree() will be executed before the createexplosion function ends.

I just want to execute the create_explosion() function and after that executes the queue_free.

if armor <= 0:
    create_explosion()
    yield(get_tree().create_timer(.5), "timeout")
    queue_free()

Thank you.

in Engine by (127 points)
edited by

3 Answers

0 votes
by (23 points)

what if yield is used in a function which is called in update cycle.? does it work ?

+13 votes

Try these steps:
1. Add a signal, let's call it exploded
2. Call it at the end of create_explosion(): emit_signal("exploded")
3. Replace the yield call

if armor <= 0:
    create_explosion()
    yield(self, "exploded")
    queue_free()

Even better if the explosion is an animation. You don't need the exploded signal anymore.

if armor <= 0:
    create_explosion()
    yield($AnimationPlayer, "animation_finished")
    queue_free()

Assuming $AnimationPlayer is used to play your explosion.

by (4,037 points)

Thanks man this works very well! There is an animation but the problem is that it is inside of the instantiate explosion (from another scene) inside of the createexplosion() function. In that way I don't know how to use the animationfinished signal in the parent node.

Here the .gd code attached to the explosion scene:

Note: pflare, psmoke and anim (AnimatinPlayer) are childs nodes from the explosion scene.
Note2: the yield($anim, "animation_finished") just works inside of the explosion scene.

extends Sprite

func _ready():
    randomize()
    rotate(deg2rad(rand_range(0,360)))
    $p_flare.emitting = true
    $p_smoke.emitting = true
    $anim.play("fade_out")
    yield($anim, "animation_finished")
    queue_free()

Here is the create_explosion function from the parent node:

func create_explosion():
    var explosion = scn_explosion.instance()
    call_deferred("add_child", explosion)
    emit_signal("exploded_wait")

Shouldn't this simply be solved by using get_node from the parent node?

yield(explosion.get_node("anim"), "animation_finished")

From the code in your question, this is what we arrive at:

func explode_if_armor_reached_zero(): # or whatever your function name is
    if armor <= 0:
        var explosion = create_explosion()
        yield(explosion.get_node("anim"), "animation_finished")
        queue_free()

func create_explosion():
    var explosion = scn_explosion.instance()
    call_deferred("add_child", explosion)
    return explosion
+5 votes

You can wait for a function's completed signal. In your case, it's

    yield(create_explosion(), "completed")

For a more complete example, consider dealinitialhands below:

func deal_initial_hands():
    # move_card_from_deck_to_position() ... i.e. run Tween
    yield(get_tree().create_timer(0.25), "timeout")
    print('a')
    # move_card_from_deck_to_position() ... i.e. run Tween
    yield(get_tree().create_timer(0.25), "timeout")
    print('b')
    # etc...

# from call site:
target.deal_initial_hands()
print('x')

If I run the code in call site (which calls deal_initial_hands(), x will print before a and b. So if e.g. you're relying on values which will be set after deal_initial_hands at call site - then you're out of luck as they don't exist yet.

However, you can wait for deal_initial_hands to finish by yielding to it's completed signal instead of just calling it:

# from call site:
yield(target.deal_initial_hands(), "completed")
print('x')

Now it'll print a, b, then x.

by (31 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.