Асинхронный метод против возврата UniTask

Я пытаюсь узнать, как работает асинхронное программирование в Unity, используя библиотеку UniTask.

Допустим, у нас есть этот код:

private async UniTask LoadGameAsync()
{
    //this should be the right way to await the scene loading
    await LoadSceneAsync("Level_01");
    Debug.Log("Level 01 finished loading.");
    
    //does this work?
    //I'm uncertain if this is correct because I await a non async method. But then again it returns a task ... No compiler error.
    await LoadScene("Level_02");
    Debug.Log("Level 02 finished loading.");
    
    //why all this?
    //because I want to load multiple scenes simultaneously and only when all are finished loading, hide a loading screen.
    //Does this work the way I intend to or are there pitfalls to avoid? If so, what's the correct way of implementing something like this?
    UniTask level03Task = LoadScene("Level_03");
    UniTask level03UITask = LoadScene("Level_03_UI");
    await UniTask.WhenAll(level03Task, level03UITask);
    Debug.Log("Level 03 and its UI finished loading, hide loading screen now.");
}

private async UniTask LoadSceneAsync(string sceneName)
{
    await SceneManager.LoadSceneAsync(sceneName).ToUniTask();
}

private UniTask LoadScene(string sceneName)
{
    return SceneManager.LoadSceneAsync(sceneName).ToUniTask();
}

Комментарии в коде в основном суммируют мой вопрос. Можно ли вернуть UniTask из метода, а затем дождаться его? Это почему-то кажется неправильным, потому что метод по сути такой же, как и асинхронный, но... не асинхронный.

Если это не работает так, как задумано, каков будет правильный способ реализовать то, что я себе представляю?

Обратите внимание, что UniTask по сравнению с Task — это структура, а не класс. Не уверен, имеет ли это значение при создании задач для дальнейшего использования.

Спасибо!

Спасибо! Тем не менее мне интересно, то же самое происходит и с UniTask, потому что UniTask — это структура, а не класс.

Meister der Magie 22.05.2024 20:32
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
351
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не уверен, правильно ли это, потому что жду неасинхронного метода. Но опять же возвращает задачу... Никакой ошибки компилятора.

Вы ожидаете не методов, а ожидаемых объектов. Пока что вы ожидаете не метод, а объект, который он возвращает. Это могут быть Task, UniTask или любые другие объекты, совместимые с ключевым словом await.

Под капотом async/await реконструируется в конечный автомат без ключевых слов async/await, а только с вызовом методов ожидаемых объектов с некоторыми вспомогательными объектами для его создания или чем-то еще. Вы можете попробовать проверить это и другие синтаксические сахара в SharpLab.

   //why all this?
   //because I want to load multiple scenes simultaneously and only when all are finished loading, hide a loading screen.
   //Does this work the way I intend to or are there pitfalls to avoid? If so, what's the correct way of implementing something like this?
   UniTask level03Task = LoadScene("Level_03");
   UniTask level03UITask = LoadScene("Level_03_UI");
   await UniTask.WhenAll(level03Task, level03UITask);
   Debug.Log("Level 03 and its UI finished loading, hide loading screen now.");

Давайте разберемся с этим.

    UniTask level03Task = LoadScene("Level_03");
    UniTask level03UITask = LoadScene("Level_03_UI");

Эти две строки будут выполнены немедленно. Они запускают процесс загрузки сцен и создают дескрипторы (UniTask), которые можно использовать для работы с этим процессом.

    await UniTask.WhenAll(level03Task, level03UITask);

В этой строке две задачи используются для создания третьей, которая будет дескриптором их выполнения. И после того, как эта задача создана, она мгновенно awaitредактируется. Таким образом, выполнение метода продолжится только после завершения ожидаемой задачи. И оно будет завершено после выполнения двух задач по загрузке сцены.

Пока что, если вы хотите отобразить любой пользовательский интерфейс загрузки, вам нужно показать его перед этой строкой и скрыть после этой строки.

Обратите внимание, что UniTask по сравнению с Task — это структура, а не класс. Не уверен, имеет ли это значение при создании задач для дальнейшего использования.

В общем, UniTask и Task имеют гораздо более глубокие различия, помимо типов struct и class. В большинстве случаев вы не заметите никаких различий между ними при работе с Unity API. Возможно, я могу отметить, что UniTask по умолчанию выполняются внутри основного цикла Unity, а Task по умолчанию выполняются в отдельном потоке, что может привести к проблемам с доступом к некоторым API Unity.

Спасибо за такой подробный и развернутый ответ! Итак, подведем итог: мой код работает так, как задумано, верно?

Meister der Magie 25.05.2024 10:15

@MeisterderMagie, верно.

Nikolai 25.05.2024 23:15

Другие вопросы по теме