0 votes

In my game I have a menu where I select different levels which are each different scenes. Going to the scenes causes the game to freeze while it loads though, so I followed the documentation's tutorial for the background loader (https://docs.godotengine.org/en/stable/tutorials/io/background_loading.html).

I have a loading bar that updates with the background loading progress and that works correctly, but it still freezes before the scene actually changes and I can't figure out why.

Here is the relevant code I'm using:

To start the loading:

func goto_level(path):
 score = 0
 call_deferred("_deferred_goto_level", path)

func _deferred_goto_level(path):
 if use_loader == true:
    loader = ResourceLoader.load_interactive(path)

    if loader == null:
        print("error happened")
        return
    set_process(true)

    wait_frames = 1

To process the loading:

func _process(delta):
 if loader == null:
    set_process(false)
    return

 if wait_frames > 0:
    wait_frames -= 1
    return

 var err = loader.poll()
 if err == ERR_FILE_EOF:
    var resource = loader.get_resource()
    loader = null
    set_new_level(resource)
 elif err == OK:
    var progress = round(float(loader.get_stage()) / loader.get_stage_count() * 30)
    loading_bar.value = progress
 else:
    print("error while loading")
    loader = null

Then to set the scene after it's loaded:

func set_new_level(scene_resource):
 current_level.free()
 current_level = scene_resource.instance()
 call_deferred("add_child", current_level)

The tutorial had a while loop in the process function but that was even worse and resulted in the game freezing for the entire loading and the loading bar not updating, not just when the scene is added.

Godot version 3.3.4
in Engine by (24 points)

I have created my own module for similar tasks. You can have a look or even use it AppDelegate. It works for any version of Godot

P.S. For a solution to your problem, look towards Threads

1 Answer

+1 vote
Best answer

kurtsev0103 comment is right. You should use a Thread:

https://docs.godotengine.org/en/stable/classes/class_thread.html

The thing is that the ResourceInteractiveLoader returned from ResourceLoader.load_interactive() is not a background loader, it is just interactive, that is, it can break up loading in steps instead of doing all steps at once, but each step is synchronous and on the same thread as the caller. If you have one resource that has only one load step, but that load step takes 5 seconds, then using the interactive loader has no difference from just using the built in load() function.

If you just use a load() call but on another thread, the game should not freeze.

by (265 points)
selected by
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 webmaster@godotengine.org with your username.