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

В каком моменте lifetime cycle объектов работает Coroutine

2.0 Middle🔥 182 комментариев
#Unity Core#Асинхронность и многопоточность

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Корутины и Lifecycle объектов в Unity

Корутина (Coroutine) в Unity — это специальный метод, который может приостанавливать своё выполнение и возобновлять его в следующих кадре или через заданное время, не блокируя основной поток. Важно понимать, что её lifetime неразрывно связан с lifetime GameObject, к которому привязан запустивший её MonoBehaviour скрипт.

Основные моменты взаимодействия

Корутина работает в рамках стандартного жизненного цикла MonoBehaviour, но с важными нюансами:

  1. Запуск (StartCoroutine): Корутина может быть запущена только из активного скрипта на активном GameObject. Стандартные точки запуска — методы Start(), Awake() или в ответ на событие (например, OnClick).
  2. Выполнение (yield): После каждого оператора yield управление возвращается движку. Корутина "засыпает" до наступления условия возобновления (следующий кадр, истечение времени, завершение асинхронной операции). В этот момент GameObject и скрипт должны оставаться активными.
  3. Остановка:
    *   **Автоматическая**: При **отключении (`enabled = false`)** скрипта, запустившего корутину, она **продолжает выполняться**. Однако, если **деактивирован сам GameObject** или он **уничтожен (`Destroy`)** — выполнение корутины **немедленно прекращается**.
    *   **Явная**: Через `StopCoroutine()` или `StopAllCoroutines()`. Важно делать это, например, в `OnDisable()` или `OnDestroy()`, чтобы избежать утечек памяти и ошибок.

Критическая точка остановки

Главный момент, когда работа корутины гарантированно прерывается — это уничтожение GameObject (Destroy(gameObject)). Деактивация объекта (SetActive(false)) также останавливает все корутины на нём. Это ключевое отличие от отключения скрипта.

Практический пример и код

Рассмотрим сценарий, где корутина должна прекратить работу при деактивации объекта.

using UnityEngine;
using System.Collections;

public class ExampleCoroutine : MonoBehaviour
{
    private Coroutine _countdownCoroutine;

    void OnEnable()
    {
        // Запускаем корутину при активации объекта/скрипта
        _countdownCoroutine = StartCoroutine(CountdownRoutine());
    }

    void OnDisable()
    {
        // ЯВНО останавливаем корутину при деактивации.
        // Это важно, если скрипт может быть отключен (enabled = false),
        // т.к. в этом случае корутина не остановится автоматически.
        if (_countdownCoroutine != null)
        {
            StopCoroutine(_countdownCoroutine);
        }
    }

    IEnumerator CountdownRoutine()
    {
        int count = 10;
        while (count > 0)
        {
            Debug.Log($"Countdown: {count}");
            count--;
            // Ждем 1 секунду перед следующей итерацией
            yield return new WaitForSeconds(1f);
            // Если здесь GameObject будет уничтожен извне,
            // выполнение прервется сразу после проверки условия yield.
        }
        Debug.Log("Countdown finished!");
    }
}

Исключение: статические классы и DontDestroyOnLoad

  • Статические классы: Корутина не может быть запущена из статического метода, так как ей требуется контекст MonoBehaviour.
  • DontDestroyOnLoad: Если GameObject помечен как DontDestroyOnLoad, то его корутины будут переживать загрузку новых сцен. Это нужно учитывать в архитектуре, чтобы избежать "сиротских" процессов.

Вывод

Корутина работает до тех пор, пока жив её родительский GameObject. Её выполнение встроено в главный цикл Unity (через механизм yield), но полностью зависит от состояния объекта. Понимание этого необходимо для:

  • Предотвращения ошибок обращения к уничтоженным объектам (MissingReferenceException).
  • Корректного управления долгосрочными процессами (загрузка, анимации, таймеры).
  • Написания чистого и безопасного кода без утечек. Всегда явно останавливайте корутины в OnDisable() или OnDestroy(), если логика требует их завершения при отключении скрипта.