← Назад к вопросам

Для чего нужна 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 разработчик!