Go, Go, Godot!
  • 0

Dynamically finding and loading resources from the Filesystem for Android and Web Exports

January 27, 2023

A little while ago, I created a type of AudioManager to make it easier to work with sound files in bulk: Rather than assigning audio streams by hand, I was doing it programmatically; reading the contents of a directory and using load() to get the resources. It worked great and saved a lot of time over assigning hundreds of sound resources by hand. While this worked during development and for Windows exports, it failed on Android and Web exports.

Godot Engine 4 will, at export time, relocate these resources. So if you are reading directly from the directory where you’re expecting a file to exist, it may no longer be there after the project is exported. Instead, you will find the same file with a “ .remap ” suffix added in its place. Just strip off that “.remap” suffix and use ResourceLoader.load() , which understands the resource mapping and can retrieve the proper resource for you.

The reason for the resource remapping is that some platforms require assets to be bundled in specific ways or stored in specific locations. The original asset has been moved, but Godot will instead have the same filename with an added “.remap” suffix to indicate that.

If you need to load something dynamically, use the ResourceLoader, and if you’re trying to discover content, scan the directory, and strip off the .remap suffix.

As long as you’re aware of this pitfall, you should be able to handle resources in your Godot game dynamically.

I’ve abstracted this into a general-purpose resource finder:

class_name GGResourceFinder
extends RefCounted

## Iterates over files in a directory
## making it easy to load contents from disk at run-time.
##
## This finder helps find resources that are remapped for Android
## and Web exports


static func find(directory: String, suffix: String) -> Array[String]:
	var files: Array[String] = _dir_contents(directory, suffix)
	files.sort()
	return files


## Recursively find files from a directory
static func _dir_contents(path: String, suffix: String) -> Array[String]:
	var dir = DirAccess.open(path)
	if !dir:
		print("GGResourceFinder: An error occurred when trying to access path: %s" % [path])
		return []

	var files: Array[String]
	dir.list_dir_begin()
	var file_name = dir.get_next()
	while file_name != "":
		file_name = file_name.replace('.remap', '') 
		if dir.current_is_dir():
			files.append_array(_dir_contents("%s/%s" % [path, file_name], suffix))
		elif file_name.ends_with(suffix):
			files.append("%s/%s" % [path, file_name])
		file_name = dir.get_next()
		
	return files

This script can then be used to find scenes from a particular directory. This may be relevant if you’re looking to support mods or DLCs in your Godot game since the game will have to have some way to discover and load the new content.

func _ready() -> void:
	_load_content_scenes()


func _load_content_scenes():
	if content_directory.is_empty(): return
	var files = GGResourceFinder.find(content_directory, ".tscn")
	for filename in files:
		var scene = ResourceLoader.load(filename)
		if scene is PackedScene:
			content_scenes.append(scene)


func _find_audio_theme_files():
	_audio_files = GGResourceFinder.find(audio_directory, ".tres")
	_audio_files.sort()

Anyway, path remapping is something to be aware of. I feel like that’s one of those things that’ll sneak up on you. Everything works great up until exporting, then suddenly everything’s broken for trying to be too data-driven. Some additional reading:

  • Godot Engine Github issue: Exporting a .gd script in pck changes the script to .gdc and .gd.remap #42507 is a discussion that involves the .remap mechanism.
  • Old Godot 2.1 docs exposed this somewhat via PathRemap.

Posted in Godot.
Share
PreviousGodot Engine 4.0 released!
NextQuickly deploying Godot games on the web with Netlify

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Related Posts

  • Godot Game Engine Logo
    September 15, 2022

    Godot Engine 4 reaches beta

    Just a couple of days ago, Godot 4.0 alpha 17 was announced. Today, Godot Engine 4.0 beta 1 was released. Be sure to check out the announcement. There are lots of improvements across the board; rendering, lighting, physics and navigation, animation, and scripting.

  • April 20, 2024

    Ditch @onready, use @export instead

    Are you using @onready to reference nodes? There’s a better way! Here’s a simple example of how many tutorials use @onready to reference nodes: That script is attached to a CanvasLayer node with a ProgressBar called HealthBar. And yet, when running the scene, it will throw an error: This is because there’s actually a spelling …

  • January 15, 2025

    Inventory System 2 Alpha 1 available

    The first alpha of the inventory system v2 is now available. For v2, a lot of refactoring work has been done with a focus on improving the developer experience. As part of that, the naming convention of the addon classes was streamlined and is more consistent now. The GDScript documentation comments have been improved significantly …

  • February 15, 2024

    Inventory System v1.8 available

    The latest version includes a few new enhancements, and an experiment: The sequencer demo uses inventory instances to hold music notes, which can be played back. This was inspired by music trackers that were popular in the 90s, such as Scream Tracker and Impulse Tracker. The sequencer isn’t meant to be a production-ready digital audio …

    © 2025 GoGoGodot.io. All rights reserved.