설명용으로 재현한 코루틴 흐름입니다. 소유 GameObject가 꺼지는 순간 실행이 끊깁니다.
설명용으로 재현한 코루틴 흐름입니다. 소유 GameObject가 꺼지는 순간 실행이 끊깁니다.

SetActive(false)는 코루틴까지 끊습니다

코루틴은 별도 스레드가 아닙니다. MonoBehaviour가 붙은 GameObject의 activeSelf가 false가 되거나 스크립트가 Destroy되면 실행이 멈춥니다. 반대로 컴포넌트의 enabled를 false로 바꾸는 것만으로는 코루틴이 자동으로 멈추지 않습니다. 이 차이를 놓치면 페이드, 타이머, 네트워크 대기 코드가 조용히 사라진 것처럼 보입니다.

using System.Collections;
using UnityEngine;

public class FadeController : MonoBehaviour
{
    [SerializeField] private CanvasGroup target;

    public void Begin()
    {
        StartCoroutine(FadeOut());
    }

    private IEnumerator FadeOut()
    {
        while (target.alpha > 0f)
        {
            target.alpha = Mathf.MoveTowards(target.alpha, 0f, Time.deltaTime);
            yield return null;
        }
    }
}

계속 살아 있어야 할 일을 분리합니다

화면을 숨기려고 컨트롤러 전체를 끄고 있다면, 코루틴을 실행하는 오브젝트와 숨길 오브젝트를 나누는 편이 낫습니다. FadeController는 켜 둔 채 CanvasGroup이나 자식 UI만 꺼 보세요. 정말 중단할 때는 시작할 때 받은 Coroutine 핸들을 저장해 StopCoroutine으로 의도를 드러내면 됩니다.

private Coroutine running;

public void Begin()
{
    if (running != null)
        StopCoroutine(running);

    running = StartCoroutine(FadeOut());
}

private void OnDisable()
{
    if (running != null)
        StopCoroutine(running);
}

코루틴을 스레드로 착각하지 않습니다

코루틴 안에서 파일 읽기나 무거운 계산을 해도 메인 스레드에서 실행됩니다. 프레임을 나누는 데는 좋지만 CPU 시간을 다른 코어로 보내 주지는 않습니다. 무거운 작업이라면 Profiler로 먼저 시간을 확인하고 Job System이나 async/await가 맞는지 따로 판단하세요.

확인한 공식 문서Unity 코루틴 매뉴얼 ↗