- Home /
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.
A naive solution would be to use FindObjectsOfTypeAll. You can use this to list all of the meshes in the resource pipeline.
To be honest, I don't like that approach very much, it feels a bit too implicit for my liking. Personally, I would create a payload manifest which explicitly directs to the relevant resource IDs. You could write a build script that generates such manifest to automate the whole process.
Either/or should work.
Actually i don't think that would work since FindObjectsOfTypeAll can only find loaded objects in memory. Since the resources he's looking for aren't loaded yet they can't be found. Haven't tried it yet, but i tried something similar in the past. I was searching for a way to find all assets (even in the editor) but it didn't work.
The description of that function says that it will return a list of "loaded" objects. I load and unload objects on the fly and need a list of unloaded objects. Also it would appear that it does not constrain the return objects to just the items int he resource folder which would mean that I would have to isolate the wanted prefabs from the unwanted ones. I do not understand your second suggestion if you could elaborate I would love to give it a try if it is a possible solution.
While this is a older post, I would actually like to suggest something a little simplier..
var listTextures = UnityEngine.Resources.LoadAll("Textures/");
var listPlayers = UnityEngine.Resources.LoadAll("Players/");
for (var oText in listTextures) {
Debug.Log(oText );
}
While this might not be ideal for everyone, if you organise your resources content with folders, then you can simple load various groups easily.
This is my preferred method as it allows you mean organise by folders and naturally i organise my project this way.
As i said, older answer but google seems to think this is the best page
The problem was to actually find what assets are available without actually loading them. If you have a lot content (like stated in the OP) you either have a lot stuff in a single folder or a lot folders with just a few assets which belongs together (like you suggested). However in both cases you have to know the asset names / folder names beforehand. There's no way to deter$$anonymous$$e which assets / folders are available at runtime. That's why i suggested to create an editor script that automatically searches for the asset names at edit time and stores them in an array so you can look them up at runtime.
Answer by Bunny83 · Jan 07, 2014 at 12:01 AM
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.
Answer by Anxo · Jan 07, 2014 at 08:42 PM
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 [i];
}
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 @Anxo, thanks for this example code, but I couldn't get it to work (I'm hopeless with editor scripts).
Is the idea that you click on a large number of items in the Project panel? And it should do something?
I guess, CharacterChanger
is your own class right?
In my case I have a few hundred AudioClip
, in folders, in Project. I just want to, essentially, get for each of those AudioClip, the folder name of the folder containing that clip. Anyways.
Answer by CarlosBCV · Jan 29, 2017 at 12:04 AM
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.
That link no longer exists.. did it ever get implemented?