Find All Objects in Resource Folder at Runtime without Resource.LoadAll

I am working on a project with about a lot of heavy geo that needs to be displayed one at at time. Best way to picture it is if you imagine a car selection screen in a racing game. You can go through a large amount of cars and have them loaded at request without having them all loaded at the same time.

This works well with Resource.Load. The problem is that I will already have to have the name of the object in the Resource folder to load it. So that I am able to just drop objects into the Resource folder and have them loaded automatically when selecting the next object in an array I looked up and wrote the following script which works well.

using System.IO;
using System.Collections.Generic;

private List<string> PlayersInFolder;

void Start ()
{
     PlayersInFolder = new List<string> ();
     string myPath = "Assets/Resources/";
     DirectoryInfo dir = new DirectoryInfo (myPath);
     FileInfo[] info = dir.GetFiles ("*.*");
     foreach (FileInfo f in info) {
	if (f.Extension == ".FBX" || f.Extension ==      ".prefab") {
	string tempName = f.Name;
	string extension = f.Extension;
	string strippedName = tempName.Replace (extension,  "");
															    PlayersInFolder.Add (strippedName);
     }
}

So this very nicely adds the name of every object with the .FBX or .prefab extension to an array of strings which I can then use to pull elements from the Resource folder. While in the editor.

The problem is that when the game is build, it compiles the content of the Resource folder and changes it’s directory. While…

Resource.Load("FBXname");

still works well, my array of names is no longer correct as this is no longer the correct directory.

         string myPath = "Assets/Resources/";
         DirectoryInfo dir = new DirectoryInfo (myPath);

So while build, the app crashes on.

FileInfo[] info = dir.GetFiles ("*.*");

I can not use Resource.LoadAll b/c there are too many heavy elements and it crashes and become out of memory.

So now how do I find the names of elements in the resource folder dynamically. I realize that I could hardcode the names into a public list of strings but by the end of the project there might be hundreds of these and they may change (add subtract and change names) so I do not wish to edit some big list of strings all the time.

The best way is using a hardcoded list of relative path names like you suggested. However if you really have a lot of objects you might want to write an editor script to create this list “automatically” by using the System.IO namespace like you did. You could write an AssetPostprocessor and use OnPostprocessAllAssets or a different callback to update your assetlist. You have to be careful since the postprocessor is called at every import. If that’s a too heavy load at edit time you could so it half-automatic by adding a menu item to start the creation of your list.

Thank you Bunny83, your suggestion for an editor script pointed me in the right direction. I was not quite sure how the AssetPost stuff works but if anyone runs into this issue in the future, here is how I solved it.

This script allows me to manually adjust the list of objects to be viewed or when you click auto populate it will populate the list with all the objects in the folder as I had working in the editor yesterday but without having to look for the names at run time.

Its like an auto hardcode = )).

using UnityEngine;
using System.Collections;
using System;
using System.IO;
using System.Collections.Generic;
using UnityEditor;

[CustomEditor(typeof(CharacterChanger))]
public class RefreshCharacterList : Editor
{	
		public GameObject CVGO ;
		public SerializedObject so ;
		public void OnEnable ()
		{
				CVGO = GameObject.FindWithTag ("GameController");
				so = new SerializedObject (CVGO.GetComponent (typeof(CharacterChanger)));
				so.ApplyModifiedProperties ();
		}

		public override void OnInspectorGUI ()
		{
				if (GUILayout.Button ("Auto Populate List")) {
						Populate ();
				}
				EditorGUILayout.Space ();
				ArrayGUI (so, "characterNames");
				so.ApplyModifiedProperties ();
		}

		public void Populate ()
		{
				List<string> players = new List<string> ();
				string myPath = "Assets/Resources/";
				DirectoryInfo dir = new DirectoryInfo (myPath);
				FileInfo[] info = dir.GetFiles ("*.*");
				foreach (FileInfo f in info) {
						if (f.Extension == ".FBX" || f.Extension == ".prefab") {
								string tempName = f.Name;
								Debug.Log ("tempName = " + tempName);
								string extension = f.Extension;
								Debug.Log ("extention = " + extension);
								string strippedName = tempName.Replace (extension, "");
								Debug.Log (strippedName + " Is in the Directory");
								players.Add (strippedName);
						}
				}
				so.FindProperty ("characterNames").arraySize = players.Count;
				for (int i = 0; i < players.Count; i++) {
						so.FindProperty ("characterNames.Array.data[" + (i.ToString ()) + "]").stringValue = players *;*
  •  		}*
    
  •  		so.ApplyModifiedProperties ();*
    
  •  }*
    
  •  void ArrayGUI (SerializedObject obj, string name)*
    
  •  {*
    
  •  		int size = obj.FindProperty (name + ".Array.size").intValue;*
    
  •  		int newSize = EditorGUILayout.IntField (name + " Size", size);*
    
  •  		if (newSize != size)*
    
  •  				obj.FindProperty (name + ".Array.size").intValue = newSize;*
    
  •  		EditorGUI.indentLevel = 3;*
    
  •  		for (int i = 0; i<newSize; i++) {*
    
  •  				SerializedProperty prop = obj.FindProperty (string.Format ("{0}.Array.data[{1}]", name, i));*
    
  •  				EditorGUILayout.PropertyField (prop);*
    
  •  		}*
    
  •  }*
    

}

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.

Resources.LoadAll