Reusing resources loaded asynchronously?

I’m doing the Complete Godot 2D course and exploring a little. The Shooting Rockets lecture describes loading a rocket scene. I thought I’d try loading asynchronously but I think I may be misunderstanding how it works. Any advice on why this doesn’t work would be greatly appreciated.

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

In _ready() the resource loading is initiated. In _process(), fire_rocket() is called if the shoot button is pressed [some code omitted]. In fire_rocket() loading status is retrieved and if loaded, the rocket is instantiated. If not loaded and the loading status is showing an error the game exceptions.

The first time the rocket is loaded this works. The second time I get an error with the status being 0, which means “The resource is invalid, or has not been loaded with load_threaded_request().”.

I thought that the resource is cached by default - so I should be able to reuse it without loading again. Am I mistaken or doing this wrong or is it something else?

Update: I got the code to work by storing the rocket scene in a global variable. However, I thought it would be kept in the resource loader so I shouldn’t need to do that.

Thanks.

Hi,

I would look into using preload to load the scene instead

Preload the scene

var myScene = preload(“res://path/to/your_scene.tscn”)

Thanks for the advice.
Preload is what was described in the lecture and I read some of the documentation about it - so I think I’m pretty clear on what it does and how it works. It seems like a good, simple way to have most of the loading work happen at compile time.
I assume the asynchronous method is useful when there are a lot of scenes and/or minimising game load time is a priority. For me, at the moment, I’m just trying to understand how the different options work.

From what i understand of it is that you use both in combination so that you have an async method that preloads the scene and then uses the await keyword until the level is fully loaded and then add it to the scene.
This means if you have a level with lots of resources that need to load then it wont show until everything is loaded and you wont get the popping in of items.

Something like below

async func load_level(level_path: String) -> void:
    # Load the level asynchronously
    var level = preload(level_path)
    
    # Wait for the level to be fully loaded
    await level

    # Once the level is loaded, add it to the scene
    var instance = level.instance()
    self.add_child(instance)

This way you can call this async method and pass in a string reference to the level_path and once its loaded it adds it to the scene.

Hope this helps :slight_smile:

For anyone who is interested in this topic, I asked on StackExchange and got a comprehensive answer on how ResourceLoader caches and what to expect from it: stack overflow answer. The solution is to store the loaded Resource in a variable.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms