I’m generating a maze that started to take a bit longer after adding more complex meshes to the individual 3D tiles.
I want to show a loading screen that right now is just a RichTextLabel with the content [wave]Generating ...[/wave].
I tried to use Thread.new() like described in the docs and I tried to use WorkerThreadPool.add_task, but in both cases the wave animation stops, which means that it’s still blocking the main thread.
What do I have to change so it runs in the background, doesn’t block the main thread so the animation plays and hides the animation when done generating?
This is my current implementation with WorkerThreadPool:
var active_thread_id := -1
func _process(_delta: float) -> void:
if not grid:
%LoadingBackground.show()
grid = Grid.new(grid_size)
active_thread_id = WorkerThreadPool.add_task(initialize)
if active_thread_id != -1:
if WorkerThreadPool.is_task_completed(active_thread_id):
active_thread_id = -1
%LoadingBackground.hide()
func initialize() -> void:
await build_grid(await generate_path())
(I made the generation function async because I thought that might not block the main thread )
I tested your code like this, it’s working for me, I can move the camera while it’s counting in the background, the main thread is not blocked, so this method itself should work.
var active_thread_id := -1
func _process(_delta: float) -> void:
if active_thread_id == -1:
print("LOADING")
active_thread_id = WorkerThreadPool.add_task(initialize)
elif active_thread_id != -2:
if WorkerThreadPool.is_task_completed(active_thread_id):
active_thread_id = -2
print("DONE")
func initialize() -> void:
await build_grid()
func build_grid() -> bool:
for i:int in 100000000:
if i % 10000 == 0:
print(i)
return true
Also, the docs says you always has to use wait_for_task_completion once the task is done (but not using it isn’t your issue here.. )
await build_grid() in your example is pretty much meaningless and does nothing other than a regular call because build_grid() is neither a coroutine nor a signal.
Remove both awaits and show the code of those functions. What happens if they just do large empty loops like in @Monday’s example? Do they still block?
If your thread is building meshes, you should do all the communication with the scene tree outside of the thread. Thread code should just create raw data and let the main thread set it up in the nodes.
What seems to be blocking is adding the meshes to the world. I’m adding duplicates of walls around the maze. Those walls have a pretty high polygon count.
But as you are saying and afaict I can’t move adding children to the scene to another thread, because I’m getting errors that I have to at least do add_child.call_deferred.
But that does move the call into the main thread again, right?
Because without adding the children everything runs smooth, but as soon as I try to add them it’s blocking again.
Maybe I have to go about this differently. Not sure how yet though.
Maybe running this loading animation in a separate thread instead.
Don’t add them to the tree all at once. How many nodes there is? Let the worker thread inform the main thread as soon as it’s create the data for one node and then let the main thread take the data and setup the node while worker thread is continuing to work on the next one. Stream it, so to speak.
If you’re using shaders, it also may be the shader compilation issue.