Quick answer: ResourcePreloader making the boot scene hang for seconds? It loads everything synchronously in _ready(). Switch to ResourceLoader.load_threaded_request.

A loading screen freezes for 4 seconds before showing progress. The ResourcePreloader on the scene loads all resources in one synchronous batch before the first frame draws.

Synchronous by Design

ResourcePreloader pre-loads all configured paths in _ready(). Synchronous, blocking. Good for tiny preloads; terrible for asset packs.

Async Pattern

ResourceLoader.load_threaded_request(path)
# later, poll:
var status = ResourceLoader.load_threaded_get_status(path)
if status == ResourceLoader.THREAD_LOAD_LOADED:
    var res = ResourceLoader.load_threaded_get(path)

Loads on background thread. Poll for status to update your progress bar. First frame draws immediately.

Subthreads for Multiple Loads

Set the use_sub_threads argument to true for nested dependencies. Parallelizes the dep graph — faster overall load time.

Keep a Cache

Once loaded, store the resources in a cache dict so they don’t re-load on scene change. Godot’s resource cache helps, but explicit references prevent garbage collection.

Verifying

The loading screen renders immediately and a progress bar updates in real time. No multi-second hang at scene change.

“ResourcePreloader is sync. For non-tiny preloads, use load_threaded_request.”

Pair the async loader with a small status-polling helper so gameplay code calls await loader.ready(path) — one line, hides all the polling boilerplate.