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.

Marten
  • 68
  • 2
  • 5
  • Yes, it is possible. [This blog](http://www.stevevermeulen.com/index.php/2017/09/using-async-await-in-unity3d-2017/) shows using async/await with another `AsyncOperation` method, `LoadSceneAsync`. It uses the code in [this github](https://github.com/modesttree/Unity3dAsyncAwaitUtil). It should "just work" with `LoadAsync`. – Ruzihm Feb 17 '22 at 17:59
  • 2
    You should move away from Resources. There is a good package for loading assets at runtime that is async, [Addressables](https://docs.unity3d.com/Packages/com.unity.addressables@1.19/manual/index.html) – hijinxbassist Feb 17 '22 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 – derHugo Feb 17 '22 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. – Ruzihm Feb 17 '22 at 21:12
  • `but they have multiple downsides` .. like what for example? ;) – derHugo Feb 18 '22 at 06:48

3 Answers3

1

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.

jin momiji
  • 11
  • 3
  • 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](/review/late-answers/33794788) – Jeff Neet Feb 13 '23 at 10:06
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.

Ruzihm
  • 19,749
  • 5
  • 36
  • 48
  • 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 Feb 18 '22 at 06:49
  • @derHugo Hmm, maybe. If I understand [this comment](https://stackoverflow.com/questions/55418055/in-unity-c-does-nets-async-await-start-literally-another-thread#comment97922535_55604269) and if the comment is correct, then I'd imagine it depends on if `LoadSomethingAsync` was started from the main thread – Ruzihm Feb 18 '22 at 07:32
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

Codemaker2015
  • 12,190
  • 6
  • 97
  • 81
  • 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. – Marten Feb 20 '22 at 22:06
  • Then you can use Addressables. But it supports only Unity 2019.3+ versions. – Codemaker2015 Feb 21 '22 at 08:02