When using ResourceLoader's .load_threaded_request, .load_threaded_get_status and .load_threaded_get I can't get a loaded resource a second time. I expected it to be cached and now I'm unsure if that is the intended functionality.
I am using Godot 4.2 on MacOS (Intel) and exploring asynchronous resource loading functionality. Here's a snippet showing some of my code:
const ROCKET_SCENE_FILE: String = "res://scenes/rocket.tscn"
func _ready():
ResourceLoader.load_threaded_request(ROCKET_SCENE_FILE) # asynchronously load the rocket scene
func fire_rocket() -> void:
var rocket_loading_status: ResourceLoader.ThreadLoadStatus = ResourceLoader.load_threaded_get_status(ROCKET_SCENE_FILE)
if rocket_loading_status == ResourceLoader.THREAD_LOAD_LOADED:
var rocket_scene: Resource = ResourceLoader.load_threaded_get(ROCKET_SCENE_FILE) # get the loaded scene
var rocket_instance: Node = rocket_scene.instantiate() # instance the scene
add_child(rocket_instance) # add to this scene
else:
assert(rocket_loading_status == ResourceLoader.THREAD_LOAD_IN_PROGRESS, "FAULT failure loading rocket resource: ResourceLoader.ThreadLoadStatus = " + str(rocket_loading_status))
func _process(delta: float) -> void:
if handle_actions:
process_actions() # read input and set state/triggers
if shoot == true:
fire_rocket()
shoot = false # reset the shoot trigger
The first time fire_rocket executes everything works as I expected: the status is THREAD_LOAD_LOADED and I successfully get the resource from the ResourceLoader. Strangely, the second time the status is THREAD_LOAD_INVALID_RESOURCE - meaning, The resource is invalid, or has not been loaded with load_threaded_request.
I thought that ResourceLoader would cache the loaded resource since the default cache mode for ResourceLoader.load_threaded_request is CACHE_MODE_REUSE. There's no explanation of what the cache modes mean, in the documentation, so I'm not certain if this is a bug or my misinterpretation. Also my C++ knowledge is so old that I don't really understand what's going on in the source code - so looking at that wasn't really helpful for me.
Does anyone know if ResourceLoader is intended to cache resources so that they can be retrieved multiple times, or if it is a one time retrieval only?
Yes there is a cache, and no you are not guaranteed to get the same object.
This is what happens to the best of my understanding:
load_threaded_request
a task is created and added to a list.load_threaded_get_status
, which will look up the task from the list.THREAD_LOAD_LOADED
, you ca retrieve the resource with load_threaded_get
, this also removes the task from the list.load_threaded_get_status
on a resource for which there is not a task you get THREAD_LOAD_INVALID_RESOURCE
.About the cache, yes, there is a cache of loaded resources. While it is not the issue at hand, I want to point out that despite there being a cache, it does not guarantee getting the same resource either, because:
The solution for you is to keep a reference of the loaded resource, of course.
The cache would come into play if there are multiple instances of this code running in the game. In an ideal situation, each of those instances could get the same resource from the cache, and it would only be loaded once.
If you keep the reference in a script variable, once the node that has the script attached is unloaded the reference count would decrease. And so once all the nodes that use this script are freed, the resource would be freed too.