• Godot Help
  • How to load little by little each frame so there are no wait times?

I'm using Godot 4.3, and I'm developing for the web so I need it to be single threaded to avoid complications.

I have a big ending scene I would like to load in the background during gameplay, but as I said I need it to be done in a single thread. Is this even possible?

ChatGPT said I can use the ResourceLoader and poll it each frame to load the resource little by little without the player noticing anything, but I'm having problems implementing that and I'm afraid ChatGPT could be hallucinating severely here. Does this magic actually exist?

    Denxel I need it to be single threaded to avoid complications

    What complications?

      kuligs2 No, that article is good but the only solution to waiting times it mentions is multi-threading, and I'm looking for a single thread solution that works distributing the loading every frame until the resource is fully loaded so the game can keep running.

        xyz Adam Scott explains it better:
        The result of this is that browsers greatly reduced where and how you can use that API. Namely, browsers nowadays require websites to be cross-origin isolated. When isolated, it does unlock the potential of SharedArrayBuffers, but at what cost?

        At the cost of having the capacity to make remote calls to other websites. Adieu game monetization. Adieu interacting with an external API.

        The issue is that during the development of Godot 4, we bet on the wrong horse: we went all-in with using threads with SharedArrayBuffers. We thought it was mainly a question of browser support (which took a step back due to the aforementioned security issues), so when all browsers finally shipped stable releases with SharedArrayBuffer, we streamlined everything around multi-threading.

        But we underestimated the difficulty of configuring cross-origin isolated websites.

        We know it has been a hurdle for a lot of users trying to publish their jam games on itch.io, which has an experimental SharedArrayBuffer option, but relying upon another feature (coep:credentialless) not supported by Safari or Firefox for Android).

        Likewise, most Web games are being published on third-party publishing platforms where the game authors may not even be able to set the required headers for SharedArrayBuffer support.

        • xyz replied to this.

          xyz I'm not saying he explains better than you. I said that to answer your question. Adam Scott explains it better than me, the answer to your question about the complications of multi-threading on the web.

          • xyz replied to this.

            Additional info:

            I have found the source ChatGPT is using to provide that answer, and it doesn't seem to be hallucinating, it's just from 3 years ago so the syntax and API calls are outdated: https://stackoverflow.com/questions/68437815/godot-how-to-instantiate-a-scene-from-a-list-of-possible-scenes

            Here is the relevant part:

            However, the above code will stop the game while it is loading the scene. Instead do Background Loading with ResourceLoader.

            First you need to call load_interactive which will give you a ResourceInteractiveLoader object:

            loader = ResourceLoader.load_interactive(path)
            Then you need to call poll on the loader. Until it returns ERR_FILE_EOF. In which case you can get the scene with get_resource:

            if loader.poll() == ERR_FILE_EOF:
            scene = loader.get_resource()
            Otherwise, it means that call to poll wasn't enough to finish loading.

            The idea is to spread the calls to poll across multiple frames (e.g. by calling it from _process).

            So more specifically, my question is if we can achieve that using Godot 4.3 and how. load_interactive() doesn't seem to exist now, and if I use ResourceLoader.load there is no poll() function.

              Denxel and if I use ResourceLoader.load there is no poll() function.

              There is in 3.6. So use that version if you need that feature.

              Toxe I think that's only for multi-threading but I may try it just to be sure. I ended deciding to leave optimization for a later stage.

              Denxel I'm not saying he explains better than you. I said that to answer your question. Adam Scott explains it better than me, the answer to your question about the complications of multi-threading on the web.

              I really meant to actually ask Adam if he has any practical advice on how to approach things in situations like yours.

                xyz It's okay, Adam was only mentioned because you asked about the complications of web multithreading. This post wasn't about that or about which Godot version was more suitable for my project. I only wanted to know if there is a way to poll the load to achieve single threaded fragmented loading in Godot 4.3.

                I may try asking a contributor, but Adam doesn't seem to be ResourceLoader's mantainer.

                • xyz replied to this.

                  Denxel Imho, they should have kept polling along with threaded loading in 4.x. Asset loading is one of the most important things in a game engine, more so because it can directly affect the player experience. Having more options there is always better.

                  That said, I doubt you'll be able to do something like polling from the main thread in 4.x without intervening into the source.

                  If you get some useful info from the maintainers - let us know.

                  Denxel ChatGPT said I can use the ResourceLoader and poll it each frame to load the resource little by little without the player noticing anything, but I'm having problems implementing that and I'm afraid ChatGPT could be hallucinating severely here. Does this magic actually exist?

                  don't listen to that chatbot

                  Denxel No, that article is good but the only solution to waiting times it mentions is multi-threading, and I'm looking for a single thread solution that works distributing the loading every frame until the resource is fully loaded so the game can keep running.

                  you could try using corroutines.

                  I think I did a test with corroutines (await) and it can continue to load while the game loop runs.
                  so you would run a function with await without await, and if you print after that it will print before the function finishes:

                  var my_scene
                  func corroutine() -> void:
                      await get_tree().create_timer(0.1).timeout
                      my_scene = load(path)
                      corroutine_finished.emit()
                  #in process when pressing a button or something:
                  print("before")
                  corroutine()
                  print("after")

                  this needs some more testing, maybe emit a signal when the corroutine finishes

                  • xyz replied to this.

                    Jesusemora load() is blocking. Putting it in a coroutine wouldn't change that whatsoever.