ResourceLoader in Godot – Complete Guide

Welcome to our hands-on tutorial exploring the ResourceLoader class in Godot 4—an essential aspect of game development within the powerful Godot Engine. Whether you’re just starting off on your game development adventure or seeking to refine your technical prowess, understanding the mechanisms for loading resources is key to building engaging and dynamic games. Join us as we dive into the world of ResourceLoader and unlock the potential it holds in streamlining your game’s resource management process.

What is ResourceLoader?

ResourceLoader is a singleton class provided by Godot Engine that is fundamental in the loading of resource files into your game at runtime. It interacts seamlessly with the filesystem, leveraging various ResourceFormatLoader.
classes to efficiently bring assets, such as textures, sounds, and scripts, from your game’s storage into its living, breathing ecosystem.

What is it for?

The purpose of ResourceLoader is multifaceted, but at its core:

  • It facilitates on-demand loading of assets.
  • It minimizes memory usage by managing resource caching.
  • It provides an interface for handling loading in multiple threads to keep your game performant.

By utilizing ResourceLoader, game developers can create dynamic experiences without overburdening the game’s memory, ensuring both a smooth development process and a seamless player experience.

Why should I learn it?

As a game developer, knowing how to use ResourceLoader effectively allows you to:

  • Optimize your game for different hardware specs by loading only what is needed when it’s needed.
  • Create complex games with a vast number of assets without sacrificing performance.
  • Implement advanced loading strategies such as asynchronous and threaded loading, which are essential for keeping games running smoothly on different platforms.

ResourceLoader equips you with the tools to make your game’s performance robust and adaptable—traits that can set your project apart in the competitive realm of game design. Let’s start harnessing the capabilities of this powerful class!

CTA Small Image - ResourceLoader in Godot - Complete Guide
FREE COURSES AT ZENVA
LEARN GAME DEVELOPMENT, PYTHON AND MORE
ACCESS FOR FREE
AVAILABLE FOR A LIMITED TIME ONLY

Developer API

For the latest version please visit the official documentation.

Example Project

You can download the project files here.

Let’s look at a basic example on how to use the ResourceLoader class. Since it is a singleton, we are able to access it’s methods directly on the class name without needing an instance!

Let us take a look at how we can dynamically load resources from our filesystem with a file path.

To begin with, lets use the ResourceLoader.Load() method to load a scene from our filesystem. For this example, we will be creating two scenes, main.tscn and scene_to_load.tscn that contains a simple Sprite2D node with an image to indicate scene changing.

In the main scene, lets create a button called “LoadNewScene” with a script and connect to it’s pressed signal. We can call ResourceLoader.Load() in ready and swap the scenes manually when the button is pressed.

This method is similar to the @GlobalScope.load() method that you are probably familiar with, but allows for a little bit more flexibility/control.

We pass the absolute path to the resource as a string, note that we need to include the file extension too. Here, since we are loading a scene, we are using .tscn, but if it was any other resource, you would want to use .tres instead.

We can pass a type hint string as an argument to inform the ResourceLoader about which resource type we are looking for, which would help it skip to using the correct ResourceFormatLoader to load this type. This should be the name of the resource in PascalCase as a string.

As a third argument, we could also pass a CacheMode enum value, which would dictate how the resource is cached when loading.

ResourceLoader.CacheMode has three possible values:

  • CACHE_MODE_IGNORE
  • CACHE_MODE_REUSE
  • CACHE_MODE_REPLACE

It defaults to CACHE_MODE_REUSE if you do not pass in a value for this parameter.

For example you could use CACHE_MODE_REPLACE to replace the existing cached resource in memory.

The ResourceLoader.exists() method can be used to check if a resource exists before attempting to load it. This method can also optionally be passed a type hint as a second parameter.

extends Button

var scene_path = "res://scene_to_load.tscn"
var scene_to_load

func _ready() -> void:
  pressed.connect(_on_pressed)
  
  if ResourceLoader.exists(scene_path, "PackedScene"):
    scene_to_load = ResourceLoader.load(scene_path, "PackedScene", ResourceLoader.CACHE_MODE_REPLACE)
  else:
    print("Requested resource does not exist at path!")

func _on_pressed():
  var scene_instance = scene_to_load.instantiate()
  get_tree().root.add_child(scene_instance)
  owner.queue_free()

Asynchronous resource loading

Using @GlobalScope.load() or ResourceLoader.load() blocks the main thread until the resource is fully loaded, which may cause the application to freeze momentarily, usually when the resource being loaded is a heavy resource that might take some time to load. In such cases, you would want to utilize asynchronous loading on another thread to load the resource in the background while the game continues to run normally.

To do this, the ResourceLoader class contains three main methods to facilitate this:

  • load_threaded_request(): We use this method to start loading the resource asynchronously.
    • The first parameter is the path to the resource.
    • The second (optional) parameter is a type hint similar, similar to how we’ve used it above.
    • The third (optional) parameter is ‘use_sub_threads’, which is a bool. When true, the resource is loaded with multiple threads, but it may slow the game down as a result while making the loading faster. This parameter defaults to false.
    • The fourth (optional) parameter is the cache mode as seen above.
  • load_threaded_get_status(): This method can be used to retrieve the status of loading of the passed in resource path. We pass the path as a parameter.
    • This method returns a ThreadLoadStatus enum value, that we can check against to find out whether the resource has been loaded or not.
    • Optionally, we could pass an empty array as the second parameter, which would populate the array with a single element. We could use the first element of that array to find out the current progress in loading the resource.
  • load_threaded_get(): This method returns the loaded resource. If this method is called before the resource is fully loaded, it blocks the main thread until it is fully loaded, so we would ideally want to call this only after we know that the loading has finished completely.

Lets create a new button called “LoadNewSceneAsync” and attach a script to it. Our scene should now look like this:

Screenshot 2024 06 18 112136 - ResourceLoader in Godot - Complete Guide

We use the load_threaded_request() method in _ready() to start loading at the resource at the given path. When the button is pressed, we can use loaded_threaded_get_status(), and check if it returns ResourceLoader.THREAD_LOAD_LOADED to find out if it has finished loading. As stated earlier, we could pass in an empty array, and if the resource is still being loaded, this would populate the array with the progress. In this example, since the resource being loaded is practically empty, we will never see it in practice but an example of how to use it can be seen below.

Finally, we use load_threaded_get() to get the resource.

extends Button

var scene_path = "res://scene_to_load.tscn"

var progress = []

func _ready() -> void:
  pressed.connect(_on_pressed)
  
  if ResourceLoader.exists(scene_path, "PackedScene"):
    ResourceLoader.load_threaded_request(scene_path, "PackedScene")
  else:
    print("Requested resource does not exist at path!")

func _on_pressed():
  var result = ResourceLoader.load_threaded_get_status(scene_path, progress)
  if result == ResourceLoader.THREAD_LOAD_IN_PROGRESS:
    print("Loading in progress: " + str(progress[0]))
  
  elif result == ResourceLoader.THREAD_LOAD_LOADED:
    var scene_to_load = ResourceLoader.load_threaded_get(scene_path)
    var scene_instance = scene_to_load.instantiate()
    get_tree().root.add_child(scene_instance)
    owner.queue_free()

Full script code

You can download the Godot project here. The project was developed and tested in version 4.2.

load_new_scene.gd

extends Button

var scene_path = "res://scene_to_load.tscn"
var scene_to_load

func _ready() -> void:
	pressed.connect(_on_pressed)
	
	if ResourceLoader.exists(scene_path, "PackedScene"):
		scene_to_load = ResourceLoader.load(scene_path, "PackedScene", ResourceLoader.CACHE_MODE_REPLACE)
	else:
		print("Requested resource does not exist at path!")

func _on_pressed():
	var scene_instance = scene_to_load.instantiate()
	get_tree().root.add_child(scene_instance)
	owner.queue_free()

load_new_scene_async.gd

extends Button

var scene_path = "res://scene_to_load.tscn"

var progress = []

func _ready() -> void:
	pressed.connect(_on_pressed)
	
	if ResourceLoader.exists(scene_path, "PackedScene"):
		ResourceLoader.load_threaded_request(scene_path, "PackedScene")
	else:
		print("Requested resource does not exist at path!")

func _on_pressed():
	var result = ResourceLoader.load_threaded_get_status(scene_path, progress)
	if result == ResourceLoader.THREAD_LOAD_IN_PROGRESS:
		print("Loading in progress: " + str(progress[0]))
	
	elif result == ResourceLoader.THREAD_LOAD_LOADED:
		var scene_to_load = ResourceLoader.load_threaded_get(scene_path)
		var scene_instance = scene_to_load.instantiate()
		get_tree().root.add_child(scene_instance)
		owner.queue_free()

 

 

Conclusion

Throughout this tutorial, you’ve seen how Godot 4’s ResourceLoader can deeply enhance your game development process, ensuring that your projects are not only efficient but also deliver a seamless experience to players. The knowledge and examples we provided are just the beginning; the more you engage with Godot and its capabilities, the more proficient you’ll become in realizing your creative vision.

If you’re inspired to continue learning and want to elevate your game creation skills to professional levels, don’t hesitate to join us in our Godot Game Development Mini-Degree. Your path to becoming a game development maestro is just a click away. Embrace the opportunity to transform your ideas into reality with Zenva, where we’re passionate about helping you achieve your dreams.

Did you come across any errors in this tutorial? Please let us know by completing this form and we’ll look into it!

FREE COURSES
Python Blog Image - ResourceLoader in Godot - Complete Guide

FINAL DAYS: Unlock coding courses in Unity, Godot, Unreal, Python and more.