Loading ScriptableAssets from folder with ResourceRequest

Hey forum. I’m trying to get my Scriptable Object data for all the songs to load asynchronously.
In the Debug.Log, all the try return a message with the correct songData’s name in Lime.
But when I add the song to the actual List, all of them are null, so I just end up with 18 empty data slots and when I Debug it, just a regular 'ol NullReferenceException.

This is what I had first. Seems to be incredibly inefficient.

allSongData = Resources.LoadAll<SongData>("Audio/SongData/").ToList();

This is what I’m trying:

private IEnumerator LoadAllSongs()
{
    allSongData = new List<SongData>();
    DirectoryInfo dir = new DirectoryInfo($"{Application.dataPath}/Resources/Audio/SongData");
    FileInfo[] info = dir.GetFiles("*.asset");
    foreach (FileInfo file in info)
    {
        //Since LoadAsync is already searching from a resources folder, we leave out Application.datapath ect.
        var request = Resources.LoadAsync($"Audio/SongData/{file.Name}", typeof(SongData));
        Debug.Log($"<color=grey>Looking for {file.Name}...</color>");
        while (!request.isDone)
            yield return null;
        try
        {
            SongData song = request.asset as SongData;
            allSongData.Add(song);
            //When I put song.name instead of file.Name it will return the red catch event.
            Debug.Log($"<color=lime>{song.name} was found!.</color>{Environment.NewLine}{file.FullName}");
        }
        catch
        {
            Debug.Log($"<color=red>{file.Name} wasn't found.</color>");
        }
    }
}

I’m using Unity 2019.4.38f1 btw.
I think the issue is var request = Resources.LoadAsync($“Audio/SongData/{file.Name}”, typeof(SongData));

Does anyone have an idea on what I should be doing here? Thanks in advance!

The Resources.LoadAsync docs state that you must omit the extension. The FileName.Name docs state that it includes the extension.

https://docs.unity3d.com/ScriptReference/Resources.LoadAsync.html
https://learn.microsoft.com/en-us/dotnet/api/system.io.fileinfo.name

1 Like

Alright it works now. Thanks. :slight_smile:
Using this method is still inefficient somehow though. It now doesn’t have the application freeze, but rather on each song loading, it stutters the framerate. I guess there’s still some room for improvement here. I’ll look into this too.

private IEnumerator LoadAllSongs()
{
    allSongData = new List<SongData>();
    DirectoryInfo dir = new DirectoryInfo($"{Application.dataPath}/Resources/Audio/SongData");
    FileInfo[] info = dir.GetFiles("*.asset");
    foreach (FileInfo file in info)
    {
        var fileName = file.Name.Replace($".asset", "");
        var request = Resources.LoadAsync($"Audio/SongData/{fileName}", typeof(SongData));
        while (!request.isDone)
            yield return null;
        try
        {
            SongData song = request.asset as SongData;
            allSongData.Add(song);
            Debug.Log($"<color=lime>{song.name} was found!.</color>{Environment.NewLine}{file.FullName}");
        }
        catch
        {
            Debug.Log($"<color=red>{file.Name} wasn't found.</color>");
        }
    }
    hasBeenInitialized = true;
}

Which could simply be caused by the Debug.Log :wink:

Btw the code is a bit weird in that it loads all songs as the method name indicates, but it also adds a song to the list after loading.

1 Like

Aah okay. I’ll remove the Debug.Log’s right now and see if that helps.

Yeah, the game should reuse that list of ScriptableAsset’s to get the SongData from them. (They contain an Intro AudioClip, a looping AudioClip, stinger AudioClip’s and float fadeDuration)
This class should only be created/running once per game-loop.
But do you mean I’m able to gather them all at once instead of gradually adding them? :hushed: