This site is currently in read-only mode during migration to a new platform.
You cannot post questions, answers or comments, as they would be lost during the migration otherwise.
+1 vote

I am reading the docs, specifically GDScript basics and there is this section about coroutines I am struggling to understand:

If you're unsure whether a function may yield or not, or whether it may yield multiple times, you can yield to the completed signal conditionally:

I was having a tough time understanding the code so I ran it in godot to see what happened. Because of the pseduorandom nature I modified the code slightly (but I don't think it changes the example). Here is my code I used:

extends Node

func generate():
    var result = rand_range(-1.0, 1.0)

    if result < 0.0:
        yield(get_tree(), "idle_frame")

    return result


func make():
    var result = generate()

    if result is GDScriptFunctionState: # Still working.
        result = yield(result, "completed")

    return result


func _ready():
    randomize()
    print(make())

Here's what I am struggling to understand:

It's my understanding that this code is supposed to always return a random number (above 0?). But sometimes I get a random number, sometimes I get a function state.

With this example, I'm not sure how yielding to the completed signal conditionally works.

This is particularly difficult, because I'm not even sure what this part of the documentation is trying to teach.

Sorry for the bad question, but thanks for reading and I hope you can help.

Godot version 3.4
in Engine by (16 points)

1 Answer

+1 vote
Best answer

yield is shorthand for connect method. yield does not make your code asynchronous and does not stop execution of your function until it is resolved.
Your code will be executed as next code:

extends Node

func generate():
    var result = rand_range(-1.0, 1.0)

    if result < 0.0:
        connect("idle_frame", get_tree(), "generate")
        return GDScriptFunctionState
    else:
        return result


func make():
    var result = generate()

    if result is GDScriptFunctionState: # Still working.
        connect("completed", self, "_on_completed")

    return result

func _on_completed():
    pass


func _ready():
    randomize()
    print(make())

Hopefully you will understand why you misunderstand yield usage. If not, here's example of how your code can be modified to work as expected:

extends Node

func generate(callback):
    var result = rand_range(-1.0, 1.0)

    while result < 0.0:
        yield(get_tree(), "idle_frame")
        result = rand_range(-1.0, 1.0)

    call(callback, result)


func make():
    var result = generate("_on_generated")


func _on_generated(result):
    print(result)


func _ready():
    randomize()
    make()

Unfortunately, you can't print result in _ready() function, because yield does not return values from coroutines.

by (1,656 points)
selected by

Thank you for this explanation. yield being shorthand for connect (and the separate return GDScriptFunctionState) is very enlightening.

This is an excelent explanation. Thank you!

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 Frequently asked questions and 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 [email protected] with your username.