Практически в любом Unity-проекте рано или поздно возникает задача выполнить действие с задержкой, постепенно изменить значение или дождаться наступления какого-либо события. Многие новички пытаются решить такие задачи через метод Update(), хотя для этого в Unity существует более удобный инструмент - Coroutine.
В этой статье разберём, что такое Coroutine, как они работают, когда их стоит использовать и каких ошибок лучше избегать.
Что такое Coroutine
Coroutine (корутина) - это специальный метод, который может приостанавливать своё выполнение и продолжать его позже.
Проще говоря, корутина позволяет выполнять код поэтапно, не блокируя основной поток игры.
Простейший пример:
using System.Collections;
using UnityEngine;
public class Example : MonoBehaviour
{
private void Start()
{
StartCoroutine(PrintMessage());
}
private IEnumerator PrintMessage()
{
Debug.Log("Начало");
yield return new WaitForSeconds(2);
Debug.Log("Прошло две секунды");
}
}
После запуска игры первое сообщение появится сразу, а второе - через две секунды.
Почему не использовать Update
Многие начинающие разработчики делают подобные проверки:
private float timer;
private void Update()
{
timer += Time.deltaTime;
if (timer >= 2)
{
Debug.Log("Прошло две секунды");
timer = 0;
}
}
Такой код работает, но быстро становится сложным, если подобных таймеров становится несколько.
Coroutine позволяют писать подобную логику значительно проще.
Как запустить Coroutine
Для запуска используется метод:
StartCoroutine(MyCoroutine());
Сама корутина должна возвращать IEnumerator.
private IEnumerator MyCoroutine()
{
yield return null;
}
Что делает yield return
Ключевое слово yield return сообщает Unity, когда нужно продолжить выполнение метода.
Например:
yield return null;
Означает:
Продолжить выполнение на следующем кадре.
WaitForSeconds
Самый популярный вариант использования.
yield return new WaitForSeconds(3f);
Корутина приостановится на три секунды.
Это удобно для:
- задержек;
- перезарядки оружия;
- анимаций;
- появления врагов;
- игровых эффектов.
WaitForSecondsRealtime
Обычный WaitForSeconds зависит от Time.timeScale.
Если игра поставлена на паузу:
Time.timeScale = 0;
ожидание тоже остановится.
Если нужно ждать независимо от времени игры:
yield return new WaitForSecondsRealtime(3f);
WaitUntil
Иногда нужно дождаться выполнения условия.
Например:
yield return new WaitUntil(() => player.IsDead);
После смерти игрока выполнение продолжится автоматически.
WaitWhile
Работает наоборот.
yield return new WaitWhile(() => loading);
Корутина будет ждать, пока переменная loading остаётся равной true.
WaitForEndOfFrame
Позволяет выполнить код после завершения текущего кадра.
yield return new WaitForEndOfFrame();
Часто используется:
- при создании скриншотов;
- работе с UI;
- чтении RenderTexture.
Запуск нескольких Coroutine
Можно запускать сразу несколько корутин.
StartCoroutine(SpawnEnemies()); StartCoroutine(UpdateScore()); StartCoroutine(PlayMusic());
Они будут выполняться независимо друг от друга.
Остановка Coroutine
Иногда необходимо остановить выполнение.
Например:
Coroutine reload;
private void Start()
{
reload = StartCoroutine(Reload());
}
private void CancelReload()
{
StopCoroutine(reload);
}
Также можно остановить сразу все корутины объекта:
StopAllCoroutines();
Использовать этот метод стоит осторожно.
Практический пример
Представим систему перезарядки.
private bool isReloading;
public void Reload()
{
if (!isReloading)
StartCoroutine(ReloadRoutine());
}
private IEnumerator ReloadRoutine()
{
isReloading = true;
yield return new WaitForSeconds(2);
ammo = maxAmmo;
isReloading = false;
}
Получается простой и легко читаемый код без множества таймеров.
Когда использовать Coroutine
Coroutine отлично подходят для:
- задержек;
- постепенных изменений;
- появления волн врагов;
- загрузки данных;
- анимаций;
- перезарядки;
- кат-сцен;
- диалогов.
Когда Coroutine использовать не стоит
Не стоит применять корутины:
- для сложной игровой логики;
- для постоянных вычислений;
- вместо полноценной системы состояний.
В таких случаях лучше использовать отдельные классы или архитектурные решения.
Частые ошибки новичков
Запускать Coroutine каждый кадр
Плохо:
private void Update()
{
StartCoroutine(MyCoroutine());
}
В результате каждую секунду создаются десятки новых корутин.
Забывать о завершении объекта
Если объект уничтожается:
Destroy(gameObject);
все его Coroutine автоматически прекращают работу.
Это важно учитывать при работе с загрузкой данных и сетевыми запросами.
Использовать Coroutine вместо любой логики
Coroutine - это инструмент для последовательного выполнения действий.
Они не заменяют архитектуру проекта.
Практический вывод
Coroutine позволяют писать более чистый и понятный код.
Вместо множества таймеров и проверок в Update() вы получаете последовательное выполнение действий, которое легче читать и поддерживать.
Именно поэтому корутины используются практически в каждом Unity-проекте.
Заключение
Coroutine - один из самых полезных инструментов Unity.
Освоив их, вы сможете проще реализовывать задержки, анимации, загрузку данных и множество игровых механик без лишнего усложнения кода.
Главное - использовать их по назначению и не пытаться заменить ими всю игровую логику.


Комментарии (2)
Обсуждение статьи. Комментарии проходят модерацию.