How to load files of an exported project the same way i do in Godot IDE?

Godot Version

Godot_v4.5.1-stable_mono_win64

Context

Trying to load texture file (*.png) on runtime. The path passed in is k_textureDir . I can find the files when debugging in Godot, but not when running the exported executable.

Question

How do I find and load files of an exported project the same way i do in Godot IDE? I really don’t want to manually copy the required file structure and files.

  private List<string> GetFilenamesInDir(string dirPath)
  {
    using var dir = DirAccess.Open(dirPath);
    List<string> nameList = new();

    if (dir == null)
      return null;

    dir.ListDirBegin();
    string fileName = dir.GetNext();

    while (fileName != "")
    {
      bool invalidFile = false;
      if (dir.CurrentIsDir())
        invalidFile = true;
      else if (fileName.GetExtension().ToLower() != "png")
        invalidFile = true;

      if (invalidFile)
      {
        fileName = dir.GetNext();
        continue;
      }
        
      nameList.Add(fileName);
      fileName = dir.GetNext();
    }

    return nameList;
  }

  private static string k_textureDir = "res://Map/Blocks/texture/";

nvm. fixed it. my solution is just to add a macro that finds the *.import if the game isn’t runnin in godot engine.

  private List<string> GetFilenamesInDir(string dirPath)
  {
    using var dir = DirAccess.Open(dirPath);
    List<string> nameList = new();

    if (dir == null)
      return nameList;

    dir.ListDirBegin();
    string fileName = dir.GetNext();

    while (fileName != "")
    {
#if DEBUG || TOOLS
      if (fileName.GetExtension().ToLower() == "import")
      {
        string originalName = fileName.Replace(".import", "");

        nameList.Add(originalName);
        fileName = dir.GetNext();
        continue;
      }
#else
      if (fileName.GetExtension().ToLower() != "import")
      {
        nameList.Add(fileName);
        fileName = dir.GetNext();
        continue;
      }
#endif
      fileName = dir.GetNext();
    }

    return nameList;
  }

I’m curious what the use case of scanning the .import folder is, and why your exported game can’t find files in your res:// folder.

Yeah. i couldn’t understand it either. My understanding is that when the project is exported, only the *.import is kept within the given res:// path. However, I don’t understand how the only files found in that directory is res://.../testgrass.png.import, but I am still able to load the filename that doesn’t have .import, GD.Load(“res://.../testgrass.png”).

My guess is that the path in res:// stores the compressed version of the png elsewhere, and only the .import file remains in that path. And that GD.Load() will use some kind of lookup table to find the png file give the original filepath, but DirAccess itself can’t access that same lookup table?

I assumed that it was using the local image path inside my current working directory, so i isolated and copied the exe and pck to a separate folder on a different drive, and it was still able to find the image, so that wasn’t true.

Anyway, here’s my test result by adding a print statement in the loop that parse the files using DirAccess and the code loads the files:

Running in Godot IDE

# Files found inside res://Map/Blocks/texture/ using DirAccess
# This is done without filtering out filetype. ie. all files are printed out
testgrass.png
testgrass.png.import


# Names of files being loaded with GD.Load(<filepath>) after filtering out
# .import
res://Map/Blocks/texture/testgrass.png

Running in exported executable

# Files found inside res://Map/Blocks/texture/ using DirAccess
# This is done without filtering out filetype. ie. all files are printed out.
# We can see that testgrass.png is not available here
testgrass.png.import

# Names of files being loaded with GD.Load(<filepath>)
# Even though testgrass.png cannot be found by DirAccess, it can still be loaded
# by GD.Load() 
res://Map/Blocks/texture/testgrass.png

Well holy crap. This solved my problem. I was having the exact same issue. Nice solve!

As of 4.4 ResourceLoader has .list_directory() which returns all resources in a directory, even after export. This will be more consistent than replacing .import and .remap file extensions

1 Like