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.