How to get list of assets at asset path?

In the editor I want to load all the assets in a given folder into an array. Once I have the asset’s name I can use AssetDatabase.LoadAssetAtPath . But how do I find out what assets are in the folder?

i.e.

folder struct

/myprojocted
-----/editorthingys
--------/thingy1
--------/thingy2
--------/thingy3

I know I want to load all assets in /myproject/eeditorthingys but I don’t know their name. how do I find out their names so I can lad them?

cheers,
Grant[/code]

I have exactly the same request…

No one can help us?

  1. You know it
  2. You have an asset build script that puts in a text file into the root that lists all files in as it has written them when adding to the bundle
    then you can get those information from that text file.

Besides the unity editor functions, you can probably also use .NET functions to read the folders contents.

Here’s a function to return an Array of all Objects of type T for all Assets in a folder, using the .NET File APIs:

	public static T[] GetAtPath<T> (string path) {
		
		ArrayList al = new ArrayList();
		string [] fileEntries = Directory.GetFiles(Application.dataPath+"/"+path);
        foreach(string fileName in fileEntries)
		{
			int index = fileName.LastIndexOf("/");
			string localPath = "Assets/" + path;
			
			if (index > 0)
				localPath += fileName.Substring(index);
				
			Object t = Resources.LoadAssetAtPath(localPath, typeof(T));

			if(t != null)
				al.Add(t);
		}
		T[] result = new T[al.Count];
		for(int i=0;i<al.Count;i++)
			result[i] = (T)al[i];
			
		return result;
	}
12 Likes

I have looked at my orginal question and see I misunderstood how loadall works. so the answer to my orignal question (untest) be to
var textures : Object[] = Resources.LoadAll("Prefabs", GameObjects); and loop over Object[ ] getting the names out.

1 Like

Hi Jonas,

I’m trying to get a list of AudioClips in an asset folder using your method, although the ArrayList is always empty.
I’m calling it as…

Object[] objects = Utils.GetAtPath<AudioClip>("/Sound/Music");

Thanks

The approach that uses .NET’s System.IO is not guaranteed to work on devices. The ‘Resources’ folder e.g. can become one big wad and filesystem calls will fail at that point.
The Resources.LoadAll approach is not great either because of the large memory load it can cause.
It’s kind of disappointing that Unity does not support a simple operation like listing your assets without side effects. This can be especially useful when you are trying to get something done quick and dirty.
Lacking this, the best approach seems to be @Dreamora’s approach of caching a list at build time.

small edit to Jonas’s function that worked better for me

    public static T[] GetAtPath<T>(string path)
    {

        ArrayList al = new ArrayList();
        string[] fileEntries = Directory.GetFiles(Application.dataPath + "/" + path);

        foreach (string fileName in fileEntries)
        {
            int assetPathIndex = fileName.IndexOf("Assets");
            string localPath = fileName.Substring(assetPathIndex);

            Object t = Resources.LoadAssetAtPath(localPath, typeof(T));

            if (t != null)
                al.Add(t);
        }
        T[] result = new T[al.Count];
        for (int i = 0; i < al.Count; i++)
            result[i] = (T)al[i];

        return result;
    }
2 Likes

Maybe I’m missing something, but why don’t you use Resources.LoadAll(string path) ? Which does exactly what you want… You just have to put the assets you want to import in the Resources folder.

Because that “loads the asset” imagine having 5000 models in there and you want to iterate over them (loading only 1 or a screenful at a time)… Resources.LoadAll() is no good here.

Hi, I’ve made a request for them to implement this.
PLEASE, VOTE IT.

https://feedback.unity3d.com/suggestions/list-assets-in-resources-folder

Thank you.

2 Likes

Added a couple modifications to be able to load assets outside the Resources folder in the Editor.

private T[] GetAtPath<T>(string path)
    {
        ArrayList al = new ArrayList();
        string[] fileEntries = Directory.GetFiles(Application.dataPath + "/" + path);

        foreach (string fileName in fileEntries)
        {
            string temp = fileName.Replace("\\", "/");
            int index = temp.LastIndexOf("/");
            string localPath = "Assets/" + path;

            if (index > 0)
                localPath += temp.Substring(index);

            Object t = AssetDatabase.LoadAssetAtPath(localPath, typeof(T));

            if (t != null)
                al.Add(t);
        }

        T[] result = new T[al.Count];

        for (int i = 0; i < al.Count; i++)
            result[i] = (T) al[i];

        return result;
    }
4 Likes

For my usecase, I have implimented this as a static method, that returns a List.
Also, I dislike for loops, so I used Select for clarity, which applies a function to a whole set.

public static List<T> GetAssetList<T>(string path) where T : class
{
    string[] fileEntries = Directory.GetFiles(Application.dataPath + "/" + path);
    
    return fileEntries.Select(fileName =>
    {
        string temp = fileName.Replace("\\", "/");
        int index = temp.LastIndexOf("/");
        string localPath = "Assets/" + path;

        if (index > 0)
            localPath += temp.Substring(index);

        return AssetDatabase.LoadAssetAtPath(localPath, typeof(T));
    })
        //Filtering null values, the Where statement does not work for all types T
        .OfType<T>()    //.Where(asset => asset != null) 
        .ToList();
}
2 Likes

I modified Deckweiss’s code to remove the extension before trying to get the files from the assetdatabase

public static List<T> GetAssetList<T>(string path) where T : class
        {
            string[] fileEntries = Directory.GetFiles( path);
  
            return fileEntries.Select(fileName =>
                {
                    string assetPath = fileName.Substring(fileName.IndexOf("Assets"));
                    assetPath = Path.ChangeExtension(assetPath, null);
                    return UnityEditor.AssetDatabase.LoadAssetAtPath(assetPath, typeof(T));
                })
                .OfType<T>()
                .ToList();
        }
6 Likes

Use AssetDatabase.FindAssets combined with AssetDatabase.GUIDToAssetPath in order to get your assets.

var assets = AssetDatabase.FindAssets("t:AnimationClip", new[] {"Assets/Animations"});
    foreach (var guid in assets) {
      var clip = AssetDatabase.LoadAssetAtPath<AnimationClip>(AssetDatabase.GUIDToAssetPath(guid));
      Debug.Log(clip);
    }

This is safer than working with Directory and IndexOf(“Assets”) because those can break randomly (for example when your project ends up in a subdir that has Assets in its name).

22 Likes

Tyranteon previous post is the best approach. Thank you. See the reference help Unity - Scripting API: AssetDatabase.FindAssets

Worth noting: AssetDatabase.FindAssets can be very slow if you have lots of assets in the project. In my project, using the Directory.GetFiles + AssetDatabase.AssetPathToGUID was about 50x faster. (~40 ms down to 0.8ms)

3 Likes

Might be a stupid question but how do I call that?

private T[ ] GetAtPath(string path) - what does the call look like and what do I have at that point? I am looking for a way to get every mesh under assets and turn off the mesh setting of read|write in order to save some memory durring gameplay.

Best solution on editor!

1 Like