Skip to content

Instantly share code, notes, and snippets.

@HilariousCow
Last active March 31, 2024 18:33
Show Gist options
  • Save HilariousCow/7f301b04c28fdf61e71f to your computer and use it in GitHub Desktop.
Save HilariousCow/7f301b04c28fdf61e71f to your computer and use it in GitHub Desktop.
Load All Prefabs In Directory
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.IO;
public static class PrefabLoader
{
//So, there's no "load all assets in directory" function in unity.
//I guess this is to avoid people using Prefabs as "data blobs".
//They'd rather you use ScriptableObjects... which is fine in some cases,
//but sometimes the thing you're blobbing is just a bunch of child transforms anyway,
//so it's huge buckets of sweat to reproduce the scene tools unity already has.
//The "AssetsDatabase.LoadAllAssetsAtPath" refers to /compound/ raw assets,
//like maya files. But it doesn't care about humble prefabs,
//which are more like compounds of assets, rather than raw assets.
//This function collates all the the behaviours you want in the directory you point it at. The path is relative to your Assets.
//i.e. "Assets/MyDirectory/"
//It returns the Prefab References, remember! Not instantiated scene objects!
//So it's only used for *editor-side* tools. Not run time.
//Quite useful in conjunction with "PrefabUtility".
public static List<T> LoadAllPrefabsOfType<T>(string path) where T : MonoBehaviour
{
if (path != "")
{
if (path.EndsWith("/"))
{
path = path.TrimEnd('/');
}
}
DirectoryInfo dirInfo = new DirectoryInfo(path);
FileInfo[] fileInf = dirInfo.GetFiles("*.prefab");
//loop through directory loading the game object and checking if it has the component you want
List<T> prefabComponents = new List<T>();
foreach (FileInfo fileInfo in fileInf)
{
string fullPath = fileInfo.FullName.Replace(@"\","/");
string assetPath = "Assets" + fullPath.Replace(Application.dataPath, "");
GameObject prefab = AssetDatabase.LoadAssetAtPath(assetPath, typeof(GameObject)) as GameObject;
if(prefab!= null)
{
T hasT = prefab.GetComponent<T>();
if (hasT !=null)
{
prefabComponents.Add(hasT);
}
}
}
return prefabComponents;
}
}
@ytjchan
Copy link

ytjchan commented May 6, 2019

@MuhammadFaizanKhan @lovancon
I also needed this functionality so I made some changes to it in this fork:
https://gist.github.com/ytjchan/b32e54233895122ab9d51156dccf6ee4

@Skylar1146
Copy link

Awesome! Thanks for sharing. For anyone else looking, if you need the subdirectories too, just add a SearchOption to the GetFiles Method like so
FileInfo[] fileInf = dirInfo.GetFiles("*.prefab",SearchOption.AllDirectories);

@maksimonishchenko
Copy link

root folder should be directory of folders for this script to work that is a pre-condition

@nick5454
Copy link

nick5454 commented Nov 12, 2021

Personally I think static methods are just evil. I could see maybe see a justification if this were an extension method. Static methods/properties makes completely untestable code. I have all my game objects in a dll with DryIoc, so I can fully mock make game objects before using them in Unity. Makes for much faster development.

So, I re-modified this so you can apply an Func parameter. For instance, I want all prefabs to be loaded and I have a MonoBehavior that specifies it's scene name it can be loaded in.

using this code I can add custom validation code within the method.

` public List LoadPrefabsByScene(string sceneName)
{
return LoadAllPrefabsOfType("Assets/Resources/Prefabs", (x) => x.Scenes.Contains(sceneName))..Select(x => x.gameObject).ToList();
}

public List<T> LoadAllPrefabsOfType<T>(string path, Func<T, bool> evaluate) where T : MonoBehaviour
{
    if (path != "")
    {
        if (path.EndsWith("/"))
        {
            path = path.TrimEnd('/');
        }
    }

    DirectoryInfo dirInfo = new DirectoryInfo(path);
    FileInfo[] fileInf = dirInfo.GetFiles("*.prefab", SearchOption.AllDirectories);

    //loop through directory loading the game object and checking if it has the component you want
    List<T> prefabComponents = new List<T>();
    foreach (FileInfo fileInfo in fileInf)
    {
        string fullPath = fileInfo.FullName.Replace(@"\", "/");
        string assetPath = "Assets" + fullPath.Replace(Application.dataPath, "");
        GameObject prefab = AssetDatabase.LoadAssetAtPath(assetPath, typeof(GameObject)) as GameObject;

        if (prefab != null)
        {
            T hasT = prefab.GetComponent<T>();
            if (hasT != null)
            {
                // validate the expression
                if (evaluate.Invoke(hasT))
                {
                    prefabComponents.Add(hasT);
                }
            }
        }
    }
    return prefabComponents;
}`

Hope this helps someone, Cheers!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment