← Назад к вопросам
Для чего нужна Coroutine в Unity?
1.3 Junior🔥 301 комментариев
#Unity Core#Асинхронность и многопоточность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Coroutines в Unity
Coroutine (сопрограмма) — это функция, которая может паузировать своё выполнение и продолжить позже. Это невероятно мощный инструмент для написания асинхронного кода в Unity, позволяя растянуть логику на несколько кадров или секунд.
Основные концепции
1. Что такое Coroutine
Обычная функция выполняется полностью за один раз:
void RegularFunction()
{
Debug.Log("Start");
Debug.Log("Middle"); // Выполняется сразу
Debug.Log("End"); // Выполняется сразу
}
Coroutine может паузировать выполнение с помощью yield:
IEnumerator MyCoroutine()
{
Debug.Log("Start");
yield return new WaitForSeconds(2f); // ПАУЗА на 2 секунды
Debug.Log("Middle"); // Выполняется спустя 2 секунды
yield return null; // ПАУЗА до следующего кадра
Debug.Log("End"); // Выполняется в следующем кадре
}
2. Различные типы yield
public class CoroutineExamples : MonoBehaviour
{
private void Start()
{
// Вызов coroutine
StartCoroutine(MyCoroutine());
}
private IEnumerator MyCoroutine()
{
// Пауза на определённое количество секунд
yield return new WaitForSeconds(2f);
Debug.Log("After 2 seconds");
// Пауза до следующего кадра
yield return null;
Debug.Log("Next frame");
// Пауза до конца текущего кадра
yield return new WaitForEndOfFrame();
Debug.Log("End of frame");
// Пауза до FixedUpdate
yield return new WaitForFixedUpdate();
Debug.Log("After FixedUpdate");
// Пауза с учётом deltaTime (для slow-motion)
yield return new WaitForSecondsRealtime(1f);
Debug.Log("After 1 real second");
// Пауза до выполнения условия
yield return new WaitUntil(() => someCondition == true);
Debug.Log("Condition met");
}
}
Практические применения
Пример 1: Анимация движения
public class TweenMovement : MonoBehaviour
{
public void MoveToPosition(Vector3 targetPos, float duration)
{
StartCoroutine(MoveCoroutine(targetPos, duration));
}
private IEnumerator MoveCoroutine(Vector3 targetPos, float duration)
{
Vector3 startPos = transform.position;
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
float progress = elapsed / duration; // 0 -> 1
transform.position = Vector3.Lerp(startPos, targetPos, progress);
yield return null; // Ждём следующего кадра
}
transform.position = targetPos; // Финальная позиция
}
}
Пример 2: Последовательные действия
public class DialogueSystem : MonoBehaviour
{
public void PlayDialogueSequence()
{
StartCoroutine(DialogueCoroutine());
}
private IEnumerator DialogueCoroutine()
{
// Показываем первую фразу
ShowText("Hello!");
yield return new WaitForSeconds(2f);
// Показываем вторую фразу
ShowText("How are you?");
yield return new WaitForSeconds(2f);
// Показываем третью фразу
ShowText("Goodbye!");
yield return new WaitForSeconds(2f);
HideText();
}
private void ShowText(string text) => Debug.Log(text);
private void HideText() => Debug.Log("Hidden");
}
Пример 3: Эффект fade (затухание)
public class FadeEffect : MonoBehaviour
{
private CanvasGroup canvasGroup;
public void FadeOut(float duration)
{
StartCoroutine(FadeOutCoroutine(duration));
}
private IEnumerator FadeOutCoroutine(float duration)
{
float elapsed = 0f;
while (elapsed < duration)
{
elapsed += Time.deltaTime;
canvasGroup.alpha = Mathf.Lerp(1f, 0f, elapsed / duration);
yield return null;
}
canvasGroup.alpha = 0f;
}
}
Пример 4: Ожидание события
public class EventWaiter : MonoBehaviour
{
public void WaitForPlayerInput()
{
StartCoroutine(WaitForInputCoroutine());
}
private IEnumerator WaitForInputCoroutine()
{
// Ждём, пока игрок нажмёт пробел
yield return new WaitUntil(() => Input.GetKeyDown(KeyCode.Space));
Debug.Log("Player pressed space!");
// Ждём, пока объект будет уничтожен
Enemy enemy = FindObjectOfType<Enemy>();
yield return new WaitUntil(() => enemy == null);
Debug.Log("Enemy defeated!");
}
}
Управление Coroutines
public class CoroutineControl : MonoBehaviour
{
private Coroutine currentCoroutine;
private void Start()
{
// Запуск coroutine
currentCoroutine = StartCoroutine(MyCoroutine());
}
private void StopCurrentCoroutine()
{
// Остановка конкретной coroutine
if (currentCoroutine != null)
{
StopCoroutine(currentCoroutine);
}
}
private void StopAllCoroutines()
{
// Остановка всех coroutines в этом скрипте
StopAllCoroutines();
}
private IEnumerator MyCoroutine()
{
yield return new WaitForSeconds(5f);
}
}
Преимущества Coroutines
- Читаемость: код выглядит как последовательность действий
- Управление временем: легко контролировать задержки
- Асинхронность: не блокирует главный поток
- Простота: нет callback-адов и сложной логики состояний
- Отладка: легче отслеживать ошибки
Когда использовать
✅ Используй Coroutines для:
- Анимаций и движений
- Диалогов и cutscenes
- Задержек и таймеров
- Цепочек действий
- Ожидания определённых условий
❌ Не используй Coroutines для:
- Простых вычислений (это слишком медленно)
- Критичной по производительности логики
- Множества одновременных операций (используй Job System)
Альтернативы
Для современного Unity рассмотри:
- async/await (C# 4.5+): более элегантный синтаксис
- DOTween: библиотека для анимаций и tweens
- Addressables: асинхронная загрузка ассетов
Coroutines — это фундаментальный инструмент, который должен знать каждый Unity разработчик!