3

In my Resources folder I have a subfolder for images, I would like to get all the file names of those images from within that folder.

tried several Resources.loadAll methods to afterwards get the .name but without success

was is the right practice to achieve what I'm trying to do here ?

Programmer
  • 121,791
  • 22
  • 236
  • 328
Anders Pedersen
  • 2,255
  • 4
  • 25
  • 49
  • Here, https://docs.unity3d.com/ScriptReference/Resources.LoadAll.html, there is an example that does exactly what you described (the second example). You said you tried LoadAll without success. What exactly did you try and what exactly didn't work? – Yuri Nudelman Oct 19 '18 at 10:12

2 Answers2

7

There is no built-in API to do this because the information is not after you build. You cant' even do this with what's in the accepted answer. That would only work in the Editor. When you build the project, your code will fail.

Here's what to do:

1. Detect when the build button is clicked or when a build is about to happen in the OnPreprocessBuild function.

2. Get all the file names with Directory.GetFiles, serialize it to json and save it to the Resources folder. We use json to make it easier to read individual file name. You don't have to use json. You must exclude the ".meta" extension.

Step 1 and 2 are done in the Editor.

3. After a build or during run-time, you can access the saved file that contains the file names as a TextAsset with Resources.Load<TextAsset>("FileNames") then de-serialize the json from TextAsset.text.


Below is very simplified example. No error handling and that's up to you to implement. The Editor script below saves the file names when you click on the Build button:

[Serializable]
public class FileNameInfo
{
    public string[] fileNames;

    public FileNameInfo(string[] fileNames)
    {
        this.fileNames = fileNames;
    }
}

class PreBuildFileNamesSaver : IPreprocessBuildWithReport
{
    public int callbackOrder { get { return 0; } }
    public void OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
    {
        //The Resources folder path
        string resourcsPath = Application.dataPath + "/Resources";

        //Get file names except the ".meta" extension
        string[] fileNames = Directory.GetFiles(resourcsPath)
            .Where(x => Path.GetExtension(x) != ".meta").ToArray();

        //Convert the Names to Json to make it easier to access when reading it
        FileNameInfo fileInfo = new FileNameInfo(fileNames);
        string fileInfoJson = JsonUtility.ToJson(fileInfo);

        //Save the json to the Resources folder as "FileNames.txt"
        File.WriteAllText(Application.dataPath + "/Resources/FileNames.txt", fileInfoJson);

        AssetDatabase.Refresh();
    }
}

During run-time, you can retrieve the saved file names with the example below:

//Load as TextAsset
TextAsset fileNamesAsset = Resources.Load<TextAsset>("FileNames");
//De-serialize it
FileNameInfo fileInfoLoaded = JsonUtility.FromJson<FileNameInfo>(fileNamesAsset.text);
//Use data?
foreach (string fName in fileInfoLoaded.fileNames)
{
    Debug.Log(fName);
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
-1

If you're making a tool or something, this might work for you.

(Note this only works on the Editor, will not work on your build)

using System.IO;

Const String path = ""; /folder path
private List<Texture2D> GetImages()
{
   List<Texture2D> imageList = new List<Texture2D>();
   //This is an array of file paths
   string[] files = Directory.GetFiles(path, "*.png");

   foreach (string file in files)
   {
       string fileName = Path.GetFileName(file);
       Debug.Log(fileName);

       //If you want to use those images.
       byte[] bytes = File.ReadAllBytes(file);
       Texture2D text2d = new Texture2D(0, 0);
       text2d.LoadImage(bytes);
       imageList.Add(text2d);
   }

   return imageList;
   //GUI.DrawTexture() away.
}

If you want to do something like this on build might I introduce addressable https://docs.unity3d.com/Packages/com.unity.addressables@0.8/manual/index.html

Const String imageGroupKey = ""; //Group key for those images
//not limited to Texture2D, can also be Sprite or something
Addressables.LoadAssetsAsync<Texture2D>(imageGroupKey , obj =>
{
    Debug.Log("Files = " + obj.name);
});

Edited answer, forgive my 5 yrs younger self for not clarifying where to use the codes. I've cause a lot of trouble for people who found this answer.

Gailbert
  • 115
  • 7
  • 4
    When the game is built, this function will not work. Resources are compiled and binarized – Ivaylo Slavov Aug 21 '21 at 18:10
  • 1
    this solution should never be an accepted answer, 1st: as soon as you build the game, then the content of the folders is packed into a "resources.asset" file, no one can after that detect what file was holding what... 2nd: in Editor mode you need to call the methods for ***Resources.LoadAll*** – ΦXocę 웃 Пepeúpa ツ Mar 29 '23 at 12:51
  • Looks like I've cause you guys some trouble, sorry about that. I edited it to be cleared now. – Gailbert Mar 30 '23 at 18:18