Hi,
I’m trying to implement async resource loader with UniTask based on example in documentation and got confused how to get the loaded Sprites from LoadResourcesAsync() function.
public static async UniTask<Sprite[]> LoadResourcesAsync(List<string> resourcePaths)
{
List<UniTask<Sprite>> SimultaneousLoad = new List<UniTask<Sprite>>();
foreach (string Path in resourcePaths) {
SimultaneousLoad.Add(LoadAsSprite(Path));
}
var loadedResources = await UniTask.WhenAll(SimultaneousLoad);
// >>> Confusion point 1: Here I can access individual sprites as "loadedResources[0]" for example which is expected <<<
return loadedResources;
}
public static async UniTask<Sprite> LoadAsSprite(string path)
{
var resource = await Resources.LoadAsync<Sprite>(path);
return (resource as Sprite);
}
...
var AsyncLoadedSprites = LoadResourcesAsync(new List<string>(){"Path_1", "Path_2", "Path_3"});
// >>> Confusion point 2: Here I can no longer access individual sprites as "AsyncLoadedSprites[0]" even though I'm returning basically the same value <<<
Thank you very much! I understood what my mistake was.
I’m in a bit of a pickle here though.
At some point I need to return instance of a class containing data including loaded sprites.
And if I need to var AsyncLoadedSprites = await LoadResourcesAsyn() returning method should be async and therefore would not be able to return instance of a class.
Is it possible to return and use something from async function?
E.g.
public static async DataClass LoadResourceData() {
LoadedResources = new DataClass();
LoadedResources._Sprites = async LoadResourcesAsync(new List<string>(){"Path_1", "Path_2", "Path_3"});
return LoadedResources; // <--- This won't work since async function can only return void or Task
}
async isn’t a return type, it’s a keyword that indicates to the compiler that this method runs asynchronously.
And the answer is in your other methods. Just make the return type UniTask.
It’s worth noting async and Task/UniTask is just a huge amount of compiler magic that is mostly hidden from you, the user. When you have a return type of Task or UniTask and you return just T, the compiler is wrapping it up in the Task object, and then unwrapping it on the other end.
I also understood that I need to propagate async/await to upper layer - to initial caller that doesn’t return a value.
One issue though still remains. One of the callers is the class constructor at top most layer and I cannot make it async as I understand.
It seems I need to change something in the architecture.
Correct. The top-most method is generally async void, meaning asynchronous but does not return a value. You can also use it for ‘fire and forget’ methods that operate asynchronously.
Methods you want to await on but don’t need a return value you use a ‘return’ type of Task/UniTask, and those you do want a return value you use Task/UniTask.
Correct. So you will have to do this outside of constructors. It shouldn’t be too hard swap a constructor with an async void Initialise method you introduce yourself.