ResourceLoader

Posted on 20-04-2016

Within Unity you can easily load objects in runtime from the resources folder. These objects can be anything, ranging from prefabs to sprites. It can be done with the following code.

Object o = Resources.Load("FolderName/ObjectName") as Object;

Using this function a ton, I quickly found out there were 2 downsides. First of all the fact you have to write the complete folder path, which could lead to errors if people moved around object in the editor without updating the code. The second problem arose from the fact it doesn’t cache objects. After growing increasingly frustrated with these problems, I decided to write a script which would solve this. The main premise is pretty simple. Upon initializing the code, it would loop through all subfolders from the resources folders. If these folders were filled with objects, it would save the path and the object name in a <string, string> dictionairy. Upon using the GetAsset function, it would check if the previously mentioned dictionairy had a matching object name, and would return the path. Using this path it would then use the path to load the object. The object will be cached and returned to the user.

public T GetAsset(string name)
{
// Make sure we've already instantiated
if (!hasInstantiated)
Initialize();

// Check if assets exist
if (!loadedAssets.ContainsKey(name))
LoadAsset(name);

// Return the asset
return (T)loadedAssets[name];
}

private void LoadAsset(string name)
{
// Load asset
object newObject = Resources.Load(foundPath[name] + name, typeof(T));

// Add it to the dict if it's not null
if (newObject != null)
loadedAssets.Add(name, newObject);
}

If the environment is the Unity Editor, the code will loop through each subfolder in the Resources loader, and for each object found it will write the object name and path to a .txt file. It is done in the Editor only, since Unity removes folders when a build is made.

private void Initialize()
{
#if UNITY_EDITOR
// Check/Create the correct folder & text file
CheckForFolder();

// Look for all files in the folder and get the path
CheckFolderRecursively();

// Save all found paths in the text asset
StreamWriter file = new StreamWriter(Application.dataPath + "/Resources/ESSENTIALS/ResourceLoader_Paths.txt", false);

foreach (KeyValuePair<string, string> value in foundPath)
file.WriteLine("Name:" + value.Key + ", Path:" + value.Value + ".");

file.Close();

// Make sure we reset the dictionairy
foundPath.Clear();

// Refresh the database
UnityEditor.AssetDatabase.Refresh();
#endif
}

private void CheckForFolder()
{
// If the directory does not exist, we create it
if (!Directory.Exists("Assets/Resources/ESSENTIALS"))
Directory.CreateDirectory("Assets/Resources/ESSENTIALS");
}

private void CheckFolderRecursively(string folderName = "")
{
// Find all the assets in the folder, and add these to the list
FileInfo[] assetInfo = new DirectoryInfo("Assets/Resources/" + folderName).GetFiles("*.*");

// Loop through all found assets, and add these to the list
foreach (FileInfo file in assetInfo)
// Make sure we don't get duplicate files
if (file.Extension != ".meta")
// Get the file data and add this to the list
AddFileToDict(Path.GetFileNameWithoutExtension(file.Name), folderName);

// Get all the folders from the current folder
DirectoryInfo[] fileInfo = new DirectoryInfo("Assets/Resources/" + folderName).GetDirectories();

// Loop through all folders in the current folder, and call these as well
foreach (DirectoryInfo file in fileInfo)
CheckFolderRecursively(folderName + file.Name + "/");
}

Although I’m still improving the code, a working copy can be downloaded here