godot: Godot 3.0 is not exporting/loading png files that are not hardcoded.

Operating system or device, Godot version, GPU Model and driver (if graphics related): Debian 9 / Godot 3.0-beta

Issue description: So I have this path "res://object/block/sprites/" which contains serveral .png files which I use as textures for my object.

At runtime I do this:

func load_block_texture_list():
	var texture_dir = "res://object/block/sprites/"
	var file_list = Util.get_files_in_dir(texture_dir)
	
	for file in file_list:
		if not file.ends_with(".import"):
			block_texture_list.append(load(texture_dir + file))
	
	block_texture_list_size = block_texture_list.size()

So I’m ignoring .import files because load() throws an error when you try to load them. So then in my object, I just select a random texture from that list, and assign it to the sprite. It works just fine on the Editor.

However, when exporting the game, it doesnt work. The texture list is empty, because all that godot exported to that path are the .import files, and my png files are not there.

How can I solve this?

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 30 (10 by maintainers)

Most upvoted comments

I feel kinda stupid, but I don’t understand: Godot 3.1.1, there is a place in Godot Export Settings to list “resources TO BE included” and those “resources to be included” are not included in any .pck or .apk package, both Windows and Android exports.

So, why this issue has been marked as “CLOSED” ?

Still an issue. There should be a more user friendly solution for this.

This is already being tracked in https://github.com/godotengine/godot-proposals/issues/1632.

@FeralBytes @burstina

I found a solution or just an understanding of the exporting. Like the script you posted, when looking for an asset to dynamically load, I look for the path to the .import file instead of the actual file.

For my use case I just want to get the paths of all files in a folder and will load them dynamically. So I just search for files ending with .import, then removed the .import from the path and the you can load like you normally would. So you can just call load on the items in the array returned by the function below via load(file_paths[i])

func get_file_paths_in_folder(folder_path: String) -> Array:
	
	var file_paths := []
	
	var dir := Directory.new()
	dir.open(folder_path)
	dir.list_dir_begin(true, true) # true, true params to skip hidden and navigational
	
	while true:
		var file := dir.get_next()
		if file == "":
			break
		if !file.ends_with(".import"):
			continue 
		file_paths.append(folder_path + file.replace(".import", ""))

	dir.list_dir_end()
	
	return file_paths

If this isn’t a bug then it should be a lot more user friendly. Having to go into the .import folder and hunt down a file name that looks like this (Monroe.JPG-dfd22a5596c15b36d72ef027899a9b46.stex) for every single picture you want to dynamically reference is stupid. And sure I can write a script to pick them out, but why the heck is this intended feature so obtuse?!

Just chiming in with a solution I found to work.

Create dummy nodes for all your resources. Then use/duplicate those nodes.

I know it’s a pain in the butt, and more effort than it should be, but it’s the most reliable way I’ve found.

This is not a bug: resources are imported into the .import folder. It doesn’t make sense to also keep the original file, so those are not included in the export. So if you list the directory, you’ll only find the *.import files since the original PNG is not included (only the imported version is).

The solution is to look for the *.import files instead, since those are present in the exported project.

@naturally-intelligent This is my more advanced work around. Hopefully the comments help explain what is going on.

func list_files_in_directory(path):
    var files = []
    var dir = Directory.new()
    dir.open(path)
    dir.list_dir_begin()
    while true:
        var file = dir.get_next()
        if file == "":
            break
        elif not file.begins_with("."):
            files.append(file)
    dir.list_dir_end()
    return files
    
func get_files_in_dir_after_import(path):
    var temp_array = list_files_in_directory(path)
    var file_array = []
    for file in temp_array:
        if file.ends_with('.import'):  # Handles the final exported version of the game.
            var file_name = file.replace('.import', '') # this will give something like "sprite_1.png"
            file_array.append(file_name)
        elif file.ends_with('.png'):  # Handles the testing in editor version of the game.
            file_array.append(file)
    return file_array

You can also see this has been an issue for several. I plan to make a documentation fix, but deciding where to put that fix? Also some discussion on Reddit.

I would do the opposite: list all the .import files the use load() with the extension changed to .png.

If you add *.png to the filter they don’t get exported in the same place because they’re already imported as resources (not sure if it’s intended, but it’s what happens currently).

I am currently working on a face generator, where a face is put together from different eyes, mouths, hair, etc. All PNG files depicting eyes are in a folder face/eyes, all hair is in face/hair, etc. I thought I am clever and could dynamically iterate through the eyes directory and load all contained eyes, then do the same for the other directories. Works like a charm in the editor, however, it turns out that when the project is exported, the PNG files cannot be found anymore. Using the .import files is no option for me, since the file location holds information about the type of the face part. Is there an easy solution to this problem (besides loading every image with typing out preload…) that I have overlooked? Otherwise, I don’t think this problem should be closed.

Regarding this issue… Recently, I decided to export my 1st Godot game and went through a similar situation… Man… was I pissed… Although the game was working well, in the IDE, the exported packages (both Windows and OSX) were not able to find a dozen different resources (.oog, .wav and .png). After getting to this page (without figuring the issue out) I finally did a thorough check and this is what I get: There is an issue in the IDE - and it has to do with the way it is too much forgiving, when it comes to finding files and paths, opposite to the final loader that demands files and paths references to be precise (as expected from the beginning and, if enforced by the IDE would avoid these post- export ‘surprises’). In my case, since I used some double slashes where they weren’t supposed and some capital letters (when they didn’t exist, in the real files names) I got game resources that the IDE was able to find but the post-export loader was not. In a nutshell: try and remove (or replace with ‘_’) spaces from your files names, check the expelling for capital letters (making sure they are exactly the same both in your driver and in your load commands, for instance) and make sure the double slash is just present after the ‘res:’ (Windows and OSX - not sure about Linuxes). Another good idea is, from time to time (if you change a lot), to clean the .import folder, since the IDE will not remove unnecessary files from there and you’ll end up with ‘doubles’ (you know, different hashes) that are not necessary. Cheers.

You don’t have to go in the import folder, use load("res://original_path.png").

Hi @vnen. So I’ve changed the loop for this:

for file in file_list:
	if file.ends_with(".import"):
		var file_name = file.replace(".import", "") // this will give something like "sprite_1.png"
		
		block_texture_list.append(load(texture_dir + file_name))

And it now works for a linux export, I have yet to try it on Android… Seems a bit odd.