How to track progress of a for-loop / not have it run in a single frame?

Godot Version

4.3

Question

Hello!
I’m doing some procedural generation in tilemaps in Godot and it requires some nested loops and stuff that can take a while to run - not super long yet, but perhaps ten seconds.

Now before game dev I used to write stuff in Python, and for this case I wrote myself a progress bar that I can plug into the for loop, that updates the progress bar every loop iteration - both so I can confirm new code is doing something and to see if it will complete in reasonable time.

So I tried to implement this in Godot but figured it does not work because the for loop runs in a single frame and thus the game just freezes until the loop is done.

Im just at the beginning of my generation, the waiting times will get longer - is there a way to circumvent or possibly override the single frame for loop to update the progress on screen?

Most preferred would be a reusable solution, one that I can plug into any for loop. In python I would start my timer function once before the loop starts, initializing it with the loop length and then call update once per loop iteration.

Thanks in advance!

Yeah, the way I’d generally go about this is to do one iteration per frame. Here’s some relevant documentation, and an example:

# we could have this function connected to a signal
func _on_some_event():
    do_slow_computation()

# or we could look for some condition in _process
func _process(_delta):
    if some_condition:
        do_slow_computation()
        # don't do the computation again right away
        some_condition = false

func do_slow_computation():
    for x in range(100):
        print("doing stuff")
        # wait for next frame
        await get_tree().process_frame

The idea is that because do_slow_computation uses await, it becomes a coroutine, and if we call it without awaiting it, it’ll simply run concurrently with the main thread, doing its thing. It’s important that we don’t await directly in _process - we typically do not want the _process function to be a coroutine.

1 Like

Aha! Thank you so much, what a neat, simple solution!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.