Dynamically finding and loading resources from the Filesystem for Android and Web Exports
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 just assigning hundreds of sound resources by hand. And while this worked during development and for Windows exports, it failed on Android and Web exports.
Godot Engine 4 will, at export time, shuffle around and remap some of these resources. So if you are reading directly from the directory where you’re expecting a file to exist, it may be there after the project was exported. Instead, you might find the same file with a “.remap” suffix. Just strip off that “.remap” suffix and instead of using
load()
directly, use
ResourceLoader.load()
, which understands the resource mapping and will be able to retrieve the proper resource for you.
The reason 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 dynamically handle resources in your Godot game.
I’ve abstracted this into a general resource-aware file finder:
class_nameGGResourceFinderextends 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 exportsstaticfuncfind(directory:String,suffix:String) -> Array[String]:var files:Array[String] =_dir_contents(directory, suffix) files.sort()return files## Recursively find files from a directorystaticfunc_dir_contents(path,suffix) -> 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 kind of way to discover and load the new content.
func_ready() -> void:_load_content_scenes()func_load_content_scenes():if content_directory.is_empty(): returnvar files = GGResourceFinder.find(content_directory,".tscn")for filename in files:var scene =ResourceLoader.load(filename)if scene isPackedScene: 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 4 has a bug (#50824) that causes particle jitter when the game is paused. It does look quite distracting. The Bug in Action This is a proof-of-concept wave shooter running in Godot Engine 4.0.2. Pausing the game was initially just a simple process_mode toggle. But as shown in the video clip above, there …
The Terrain3D addon for Godot lets you create and manage 3D terrains within Godot. It looks quite promising for making landscapes, hills, valleys, and other natural environments. The addon provides tools for sculpting the terrain, and you can paint different textures like grass, dirt, or rock, and blend them smoothly. It also supports features like …
I use an app called barrier. It allows you to share your mouse and keyboard with multiple devices. I use it, because I tend to have my laptop and Macbook sitting next to my PC, and it makes working across all devices very convenient. It’s a mix of a multi-monitor and multi-computer setup. Concept Your …
Here’s a collection of tutorials that are helpful if you’re new to using Control and Container nodes to create UIs in Godot 4. The Game Dev Artisan video covers creating a simple UI with a reload indicator for a simple 2D tank game: Clear Code’s 11+ hour Ultimate Introduction to Godot 4 has a chapter …
Dynamically finding and loading resources from the Filesystem for Android and Web Exports
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 just assigning hundreds of sound resources by hand. And while this worked during development and for Windows exports, it failed on Android and Web exports.Godot Engine 4 will, at export time, shuffle around and remap some of these resources. So if you are reading directly from the directory where you’re expecting a file to exist, it may be there after the project was exported. Instead, you might find the same file with a “.remap” suffix. Just strip off that “.remap” suffix and instead of using
load()
directly, useResourceLoader.load()
, which understands the resource mapping and will be able to retrieve the proper resource for you.The reason 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 dynamically handle resources in your Godot game.
I’ve abstracted this into a general resource-aware file finder:
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 kind of way to discover and load the new content.
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:
Related Posts
The Pause Handler: Working around Godot 4’s particle jitter bug
Godot Engine 4 has a bug (#50824) that causes particle jitter when the game is paused. It does look quite distracting. The Bug in Action This is a proof-of-concept wave shooter running in Godot Engine 4.0.2. Pausing the game was initially just a simple process_mode toggle. But as shown in the video clip above, there …
Terrain3D for Godot has been released
The Terrain3D addon for Godot lets you create and manage 3D terrains within Godot. It looks quite promising for making landscapes, hills, valleys, and other natural environments. The addon provides tools for sculpting the terrain, and you can paint different textures like grass, dirt, or rock, and blend them smoothly. It also supports features like …
Share your Computer’s Mouse and Keyboard with your Steam Deck
I use an app called barrier. It allows you to share your mouse and keyboard with multiple devices. I use it, because I tend to have my laptop and Macbook sitting next to my PC, and it makes working across all devices very convenient. It’s a mix of a multi-monitor and multi-computer setup. Concept Your …
Building UIs in Godot 4
Here’s a collection of tutorials that are helpful if you’re new to using Control and Container nodes to create UIs in Godot 4. The Game Dev Artisan video covers creating a simple UI with a reload indicator for a simple 2D tank game: Clear Code’s 11+ hour Ultimate Introduction to Godot 4 has a chapter …