0

Is it possible in Unity to do something like this?

private async void LoadSomethingAsync()
{
    AudioClip clip = await Resources.LoadAsync<AudioClip>("path");
}

I know I could use Unitys Coroutines instead, but they have multiple downsides why I would like to use something like the code above.
On the internet I didn't found something that works for me either, so maybe someone of you knows if something like the code above is possible or not.

5
  • Yes, it is possible. This blog shows using async/await with another AsyncOperation method, LoadSceneAsync. It uses the code in this github. It should "just work" with LoadAsync<T>. Commented Feb 17, 2022 at 17:59
  • 2
    You should move away from Resources. There is a good package for loading assets at runtime that is async, Addressables Commented Feb 17, 2022 at 18:16
  • 1
    if something like the code above is possible or not .. even if, you anyway will have to make surethe result is used in the main thread in the end since most of Unity API can not be used on other threads Commented Feb 17, 2022 at 18:34
  • 1
    @hijinxbassist I wrote an answer below for some Addressables guidance. You seem to know about the topic so please let me know if I can improve the answer. Commented Feb 17, 2022 at 21:12
  • but they have multiple downsides .. like what for example? ;) Commented Feb 18, 2022 at 6:48

4 Answers 4

2

You can try this.This library makes all Unity AsyncOperations and Coroutines awaitable: https://github.com/Cysharp/UniTask
Also, it is not recommended to combine async with void as in the code in question.

Sign up to request clarification or add additional context in comments.

2 Comments

While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From Review
This is one of the rare cases where I agree with the "just use this library" answer. There is almost no argument for not using UniTask in async Unity code.
0

I've never used Addressables, but here is some relevant documentation:

Addressables also supports asynchronous await through the AsyncOperationHandle.Task property:
public async Start() {
    AsyncOperationHandle<Texture2D> handle = Addressables.LoadAssetAsync<Texture2D>("mytexture");
    await handle.Task;
    // The task is complete. Be sure to check the Status is successful before storing the Result. 
}

So to me it seems like you could switch to using Addressables, then do this:

private async void LoadSomethingAsync()
{
    AsyncOperationHandle<AudioClip> handle = Addressables.LoadAssetAsync<AudioClip>("path");
    await handle.Task;
    if (handle.Status == AsyncOperationStatus.Succeeded) 
    {
        AudioClip clip = handle.Result;
        // use clip here
    }
    else 
    {
        // handle loading error
    }
}

Note that according to the documentation, this particular solution is not available on WebGL. This may not matter to you:

The AsyncOperationHandle.Task property is not available on WebGL as multi-threaded operations are not supported on that platform.

2 Comments

I think this still could fail since the result is not necessarily handled on the unity main thread so you might not be able to actually use that clip for Unity API calls right there
@derHugo Hmm, maybe. If I understand this comment and if the comment is correct, then I'd imagine it depends on if LoadSomethingAsync was started from the main thread
0

You can use Resources.LoadAsync(path) method for asynchronously loads an asset stored at path in a Resources folder.

The following code is an example to load an audio clip from the resource folder asynchronously,

private IEnumerator LoadAudioAsync(string path) {
    ResourceRequest resourceRequest = Resources.LoadAsync<AudioClip>(path);
    yield return resourceRequest;
    AudioClip audioClip = resourceRequest.asset as AudioClip;
}

Use can also use Addressables to load the resources. But it supports only Unity 2019.3+ versions.

public async void LoadAudioAsync(string path) {
    AsyncOperationHandle<AudioClip> resourceRequest = Addressables.LoadAssetAsync<AudioClip>(path);
    await resourceRequest.Task;
}

For more examples: https://csharp.hotexamples.com/examples/UnityEngine/ResourceRequest/-/php-resourcerequest-class-examples.html

3 Comments

Thanks for your answer. But with your solution I have to use coroutines, which I wanted to avoid for multiple reasons. Thats why I asked if it is possible to use async/await instead.
Then you can use Addressables. But it supports only Unity 2019.3+ versions.
And you'll probably want to change the return type from void to Task<AudioClip> to actually use the result.
0

Starting Unity 2023.1, all types inheriting from AsyncOperation, including ResourceRequest returned by Resources.LoadAsync, support the async/await pattern.

Task obtained by awaiting an AsyncOperation have no TResult type associated (unlike AsyncOperationHandle<TObject>.task mentioned in other answers), so we need to store the ResourceRequest and retrieve the asset later (similarly to Ruzihm's answer with handle.Result, except ResourceRequest.asset is a mere Object so we'll have to cast it). There is no status to check though, so you'll have to check for null asset.

This gives:

private static async Task<AudioClip> LoadAudioClipAsync()
{
    ResourceRequest clipRequest = Resources.LoadAsync<AudioClip>("path");
    await clipRequest;
    var clip = (AudioClip) clipRequest.asset;
    return clip;
}

/* caller code */

AudioClip clip = await LoadAudioClipAsync();
// do something with clip

Source: https://docs.unity3d.com/2023.2/Documentation/Manual/AwaitSupport.html

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.