Как стать автором
Обновить

Объясняем UniTask так, чтобы понял даже ребенок (для Unity разработчиков и не только)

Уровень сложностиПростой
Время на прочтение6 мин
Количество просмотров1.1K

Представь, что ты строишь огромный замок из LEGO. Это твоя игра в Unity! Ты хочешь, чтобы в замке двигались рыцари, летали драконы, а еще играла музыка – и всё это одновременно!

Что такое "задачи" в программировании?

Когда ты говоришь компьютеру, что делать, ты даешь ему "задачи". Например:

  • "Нарисуй рыцаря!"

  • "Подожди 1 секунду."

  • "Запусти музыку!"

Что если задачи долгие?

Иногда задачи занимают время. Например, загрузить картинку дракона из интернета может быть долго. Если компьютер будет просто ждать, пока дракон загрузится, то вся игра "замрет": рыцари остановятся, музыка выключится. Это скучно, правда?

Обычные "помощники" (Task) и "супер-помощники" (UniTask)

Чтобы игра не замирала, программисты придумали "помощников", которые могут выполнять долгие задачи так, чтобы остальная игра продолжала работать. В мире Unity есть обычные "помощники" (их называют Task), а есть супер-помощники – это и есть наш UniTask!

Вот как это может выглядеть в коде:

Пример с обычным Task:

using System.Threading.Tasks;
using UnityEngine;

public class ExampleTask : MonoBehaviour
{
    async void Start()
    {
        Debug.Log("Начинаем обычную задачу...");
        await Task.Delay(1000); // Ждем 1 секунду
        Debug.Log("Обычная задача завершена!");
    }
}

Пример с UniTask:

using Cysharp.Threading.Tasks; // Не забудьте добавить UniTask в ваш проект!
using UnityEngine;

public class ExampleUniTask : MonoBehaviour
{
    async UniTaskVoid Start() // Обратите внимание на UniTaskVoid
    {
        Debug.Log("Начинаем супер-задачу UniTask...");
        await UniTask.Delay(1000); // Ждем 1 секунду так же легко!
        Debug.Log("Супер-задача UniTask завершена!");
    }
}

Почему UniTask – супер-помощник?

  1. Очень быстрый и ловкий: UniTask работает очень быстро и не заставляет игру "заикаться" или тормозить. Он как самый быстрый рыцарь в твоем замке!

  2. Не мусорит: Представь, что после каждой выполненной задачи обычные помощники оставляют немного мусора (в программировании это называется "аллокация памяти"). Если мусора много, приходит специальный "уборщик" (Garbage Collector или GC), и пока он убирает, игра может на секундочку замереть. UniTask – очень аккуратный! Он почти не оставляет мусора, поэтому "уборщику" почти нечего делать, и игра работает плавно-плавно.

  3. Дружит с Unity: UniTask создан специально для Unity, поэтому он отлично понимает, как всё устроено в твоем игровом мире, и помогает делать классные штуки с анимацией, звуками и разными событиями в игре.

  4. Умеет ждать по-умному: Он может подождать, пока загрузится картинка, или пока пройдет одна секунда, не мешая другим делам в игре.

Пример из жизни:

Представь, что мама готовит ужин (это твоя игра).

  • Без UniTask: Мама ставит вариться суп и стоит ждет, пока он сварится. В это время она ничего больше не делает – ни салат не режет, ни стол не накрывает. Скучно!

  • С UniTask: Мама ставит вариться суп, а сама идет резать салат. Когда суп почти готов, специальный таймер (это UniTask!) ей об этом сообщает. Так всё делается быстрее и веселее!

Давайте посмотрим, как это могло бы выглядеть в коде Unity:

Вариант "Без Task и UniTask" (блокирующий, все по очереди):

using UnityEngine;
using System.Threading; // Для Thread.Sleep

public class DinnerCookBlocking : MonoBehaviour
{
    void Start()
    {
        Debug.Log("Начинаем готовить ужин (блокирующий способ).");
        CookSoupBlocking();
        // Салат начнем резать только после того, как суп СВАРИТСЯ
        CutSalad(); 
        SetTable();
        Debug.Log("Ужин готов! (блокирующий способ)");
    }

    void CookSoupBlocking()
    {
        Debug.Log("Суп: ставим на огонь...");
        Thread.Sleep(3000); // Имитация долгого процесса варки супа (3 секунды)
        Debug.Log("Суп: готов!");
    }

    void CutSalad()
    {
        Debug.Log("Салат: начинаем резать...");
        Thread.Sleep(1000); // Имитация нарезки салата (1 секунда)
        Debug.Log("Салат: готов!");
    }

    void SetTable()
    {
        Debug.Log("Стол: накрываем...");
        Thread.Sleep(500); // Имитация сервировки стола (0.5 секунды)
        Debug.Log("Стол: накрыт!");
    }
}

Если запустить такой код, игра "замрет" на время Thread.Sleep(), потому что основной поток будет ждать.

Вариант с обычным Task (асинхронно, но с нюансами для Unity):

using UnityEngine;
using System.Threading.Tasks; // Для Task и Task.Delay

public class DinnerCookTask : MonoBehaviour
{
    async void Start() // Обычный async void
    {
        Debug.Log("Начинаем готовить ужин (c Task).");

        // Запускаем варку супа и не ждем ее завершения сразу
        Task soupTask = CookSoupAsync();
        Debug.Log("Суп поставлен на огонь (Task), можно заняться салатом и столом!");

        // Пока суп варится, режем салат
        Task saladTask = CutSaladAsync();
        
        // И параллельно накрываем на стол
        Task tableTask = SetTableAsync();

        // Теперь дожидаемся завершения всех задач
        await Task.WhenAll(soupTask, saladTask, tableTask);

        Debug.Log("Ужин готов! (c Task). Все было сделано асинхронно!");
    }

    async Task CookSoupAsync()
    {
        Debug.Log("Суп (Task): ставим на огонь...");
        await Task.Delay(3000); // Имитация варки супа (3 секунды) с Task.Delay
        Debug.Log("Суп (Task): готов!");
    }

    async Task CutSaladAsync()
    {
        Debug.Log("Салат (Task): начинаем резать...");
        await Task.Delay(1000); // Имитация нарезки салата (1 секунда) с Task.Delay
        Debug.Log("Салат (Task): готов!");
    }

    async Task SetTableAsync()
    {
        Debug.Log("Стол (Task): накрываем...");
        await Task.Delay(500); // Имитация сервировки стола (0.5 секунды) с Task.Delay
        Debug.Log("Стол (Task): накрыт!");
    }
}

С Task игра тоже не замрет, как в случае с Thread.Sleep(), потому что Task.Delay работает асинхронно. Однако, как мы уже обсуждали, использование Task в Unity может приводить к небольшим "заиканиям" или дополнительным затратам ресурсов (аллокациям памяти), особенно в сложных сценариях. Теперь посмотрим на UniTask.

Вариант "С UniTask" (делаем несколько дел одновременно - оптимально для Unity):

using UnityEngine;
using Cysharp.Threading.Tasks;

public class DinnerCookUniTask : MonoBehaviour
{
    async UniTaskVoid Start()
    {
        Debug.Log("Начинаем готовить ужин (c UniTask).");

        // Запускаем варку супа и не ждем ее завершения сразу
        UniTask soupTask = CookSoupAsync();
        Debug.Log("Суп поставлен на огонь, можно заняться салатом и столом!");

        // Пока суп варится, режем салат
        UniTask saladTask = CutSaladAsync();
        
        // И параллельно накрываем на стол
        UniTask tableTask = SetTableAsync();

        // Теперь дожидаемся завершения всех задач
        await UniTask.WhenAll(soupTask, saladTask, tableTask);

        Debug.Log("Ужин готов! (c UniTask). Все было сделано эффективно!");
    }

    async UniTask CookSoupAsync()
    {
        Debug.Log("Суп (UniTask): ставим на огонь...");
        await UniTask.Delay(3000); // Имитация варки супа (3 секунды) с UniTask
        Debug.Log("Суп (UniTask): готов!");
    }

    async UniTask CutSaladAsync()
    {
        Debug.Log("Салат (UniTask): начинаем резать...");
        await UniTask.Delay(1000); // Имитация нарезки салата (1 секунда) с UniTask
        Debug.Log("Салат (UniTask): готов!");
    }

    async UniTask SetTableAsync()
    {
        Debug.Log("Стол (UniTask): накрываем...");
        await UniTask.Delay(500); // Имитация сервировки стола (0.5 секунды) с UniTask
        Debug.Log("Стол (UniTask): накрыт!");
    }
}

С UniTask игра не замрет, а задачи будут выполняться асинхронно, позволяя другим процессам (например, анимациям или вводу пользователя) продолжать работать.

Зачем это нужно?

Чтобы твои игры в Unity были:

  • Плавными: Без зависаний и тормозов.

  • Отзывчивыми: Чтобы персонажи сразу реагировали, когда ты нажимаешь кнопки.

  • Крутыми: Чтобы можно было делать много всего интересного одновременно!

Так что UniTask – это как волшебная палочка для программистов в Unity, которая помогает им делать игры еще лучше и быстрее, не создавая беспорядка!

Так почему UniTask лучше обычного Task для игр?

Давай представим, что Task – это такой обычный робот-помощник, а UniTask – это его продвинутая версия: робот-помощник нового поколения, супер-быстрый и очень умный!

  1. Меньше "мусора" – игра не тормозит!

    • Помнишь, мы говорили про "мусор" (объекты в памяти)? Обычный Task иногда оставляет после себя больше такого "мусора". Когда приходит "уборщик" (GC), игра может замереть.

    • UniTask – очень аккуратный! Он почти не "мусорит". Значит, "уборщик" приходит реже, и игра работает плавно, как по маслу!

  2. Лучше понимает Unity – меньше путаницы!

    • Task был придуман для самых разных программ, не только для игр. Иногда он может немного "запутаться" или "задуматься" (это связано со сложной штукой под названием "контекст синхронизации", о которой взрослые программисты много говорят!), что тоже может привести к небольшим остановкам в игре.

    • UniTask создан специально для Unity! Он как будто говорит на одном языке с твоей игрой. Он точно знает, когда и что нужно делать, чтобы всё работало быстро и правильно прямо в игровом мире Unity. Ему не нужно лишний раз "думать", он сразу действует!

  3. Быстрее выполняет команды – больше веселья!

    • Из-за того, что UniTask такой умный и аккуратный, он часто выполняет свои задачи быстрее, чем обычный Task. А чем быстрее всё работает, тем веселее играть!

  4. Удобнее для программистов в Unity!

    • Для тех, кто создает игры в Unity, UniTask предлагает много удобных инструментов, чтобы легко управлять анимациями, загрузкой уровней, и другими игровыми штуками, которые должны происходить незаметно для игрока.

В чём же главное различие, если совсем просто?

  • Обычный Task: Хороший помощник, но для игр в Unity он как будто немного неуклюжий и может случайно насорить или заставить игру "споткнуться".

  • UniTask: Супер-помощник, созданный специально для Unity! Он очень быстрый, чистюля (не мусорит!) и отлично ладит с игровым движком, как лучший друг.

Поэтому, когда мы делаем игры в Unity и хотим, чтобы они были супер-быстрыми и плавными, мы выбираем UniTask!

Теги:
Хабы:
+1
Комментарии1

Публикации

Работа

Ближайшие события