Resource.LoadAllAsync - where is it?

We have LoadAsync, cool, now LoadAll definitely takes longer so async on this one would make sense yah?
So where is it.

It’s not Resources, but it’s the same basic idea. If you really want a lot of fine control, move to asset bundles.

Bundles require to export them to external files and you need a bunch of boilerplate code to handle them in editor, right?

It’s right in front of you.

https://docs.unity3d.com/ScriptReference/Resources.LoadAsync.html

3 Likes

read the post - LoadALLAsync

1 Like

You’re asking for it to load the entire resources folder, correct? It clearly states it does that if you pass an empty string.

2 Likes

Lol. When in doubt, read the manual. Can’t believe I missed that.

ResourceRequest.asset returns only one object no?

1 Like

I imagine you’d cast it to an Object[ ].

Why not try it and see? You could answer that more accurately and faster by simply opening Unity.

I didn’t know you could cast an Object to an Object[ ] so I tried () and “as” and nope it doesn’t compile.
So I did my own soup casting the result to IEnumerable and building the list.
.asset is null, what am I doing wrong?

Here is the code.

    public List<GameObject> objects = new List<GameObject>();
    IEnumerator Start () {
        var timer = Time.time;
        var resourceLoad = Resources.LoadAsync ("", typeof(GameObject));
        yield return resourceLoad;
        Debug.Log (Time.time-timer);
        if (resourceLoad.asset.GetType ().IsArray) {
            var objs = (IEnumerable)resourceLoad.asset;
            foreach (var o in objs)
                objects.Add ((GameObject)o);
        }
    }

Got a reply from Unity QA it’s a bug and sent for resolution. Let’s see if resolution turns out to be removing the bit in the documentation :wink:
bug# 858737

So I guess this never got resolved? LoadAsync only loads a single asset, and there is no LoadAllAsync. The only thing I can find is this one feature request

https://feedback.unity3d.com/suggestions/resources-dot-loadallasync

But with 5 votes after 3 years, I am not holding my breath

2 Likes

Here is the corresponding bug-report:

https://issuetracker.unity3d.com/issues/resource-dot-loadasync-doesnt-load-all-gameobjects-from-the-resource-folder

If you need “LoadAll” functionality, you could build a table that contains asset paths of all resources at build time and then use this information to load and look-up assets at runtime.

That being said, Unity Technologies recommends to avoid the Resources system.

https://unity3d.com/learn/tutorials/topics/best-practices/resources-folder

1 Like

Your Google Fu is on point. Cheers.

1 Like

It’s nice and all the whole idea “avoid the resources system” but it’s mighty convenient, and it seems like the best bet when working with Android and especially WebGL. I’m struggling with this and the idea I had was the same as mentioned, just somehow have a list of the relative resource paths. It’s taking a while to crack the puzzle, though.

Using WebGL by the way you’re also limited in where you can’t hang the browser with while { !isDone }; as well…

There IS a solution if you want to do things like preload assets from Resources at your scene’s start.

Basically, you can write a TextAsset to a folder called ‘Paths’ (or whatever you’d like) in your resources folder upon the import of your asset like so…this example uses audio. This is an editor script that’s placed into an ‘Editor’ folder:

public class MyAudioPostprocessor : AssetPostprocessor
{
    private string GetFileDirectoryForResources(string inputString)
    {
        inputString = inputString.Replace("\\", "/");
        string outputString = inputString.Substring(inputString.IndexOf("Resources/") + 10);

        return outputString;

    }

    void OnPreprocessAudio()
    {
        AudioImporter audioImporter                                 = (AudioImporter)assetImporter;
        AudioImporterSampleSettings audioImporterSampleSettings     = audioImporter.defaultSampleSettings;
        audioImporterSampleSettings.loadType                        = AudioClipLoadType.DecompressOnLoad;
        audioImporter.defaultSampleSettings                         = audioImporterSampleSettings;

        string filePath                 = audioImporter.assetPath;
        string fileNameNoExtension      = Path.GetFileNameWithoutExtension(filePath);
        string fileDirectory            = Path.GetDirectoryName(filePath);
        string fullPathNoExtension      = fileDirectory + "\\" + fileNameNoExtension;

        string fileDirectoryToWriteIntoFile = GetFileDirectoryForResources(fileDirectory + "/" + fileNameNoExtension);

        File.WriteAllText(Application.dataPath + "/Global/Resources/Paths/" + fileNameNoExtension + ".txt", fileDirectoryToWriteIntoFile);

    }
 
}

Then what you do is when you preload the asset, in my case audio, you would load the text asset once you have the audio clip’s name you want to load, use textAsset.text to get the path and then use that the load the actual audio clip. This is so that then you can play audio files wherever you want, in any subfolder etc… and it’ll find it.

TextAsset pathTextAsset = Resources.Load<TextAsset>("Paths/" + AudioClipToLoadName + "_Path");
            string audioPath              = pathTextAsset.text;
            AudioClip audioClip         = Resources.Load<AudioClip>(audioPath);

            preloadedAudioClips.Add(audioClip);

That way you avoid uses LoadAll at all. The only thing that would make LoadAll useful would be Async, but there are ways around it.

I think this is a good solution if you’re making a simple WebGL game and want to load audio that’s gonna be packed up inside your built game. The only thing you then have to focus on externally is save/load files.

1 Like

Wouldn’t it be way simpler if you either:

  1. Add a MonoBehaviour to a gameobject in your scene that has an array of AudioClip’s and serves of some kind of audioclip database.
  2. Add a reference to the AudioClip in the MonoBehaviour where you want to play it.
1 Like

@Peter77 The game object would just have to be global and hold audioclips, then when a scene loads in it’s preloading process it needs to detect in your events in your scene where a PlayBGM would happen or whatever your event is called and preload that clip, then unload the clips when the scene transfers into the next one…unless you’re just streaming the clips. It would be like a scene manager - > audio manager that would have that array or list of audio clips I guess, then maybe make some methods like PreloadClip() UnloadAll() and all that. I don’t know if there’s an easier way than that.

If there is a reference to an AudioClip in a scene, Unity loads the clip automatically, unless you disable the “Preload Audio Data” option on the clip:

If you switch to another scene, Unity unloads the AudioClip when no longer used.

There shouln’t be any need for a global manager if you just want to have that basic preload/unload built-in functionality.