객체 파괴 시 자동 취소 (Destroy 연계)

GetCancellationTokenOnDestroy()

UniTask는 MonoBehaviour가 파괴되는 시점에 자동으로 CancellationToken을 취소해 주는 확장 메서드를 제공함.

public class MyLoader : MonoBehaviour
{
    async UniTaskVoid Start()
    {
        // 이 객체가 Destroy되면 token이 Cancel되어 대기 중인 await가 즉시 해제됩니다
        await LoadAndBuildAsync(this.GetCancellationTokenOnDestroy());
        Debug.Log("Load 끝");
    }

    async UniTask LoadAndBuildAsync(CancellationToken token)
    {
        // 긴 로딩 시뮬레이션
        await UniTask.Delay(TimeSpan.FromSeconds(5), cancellationToken: token);
        if (token.IsCancellationRequested) return;
        // ... 나머지 빌드 작업
    }
}

CancellationTokenSource 직접 관리

때로는 Destroy와 무관하게 직접 취소 시점을 제어하고 싶을 때가 있음

public class MyWatcher : MonoBehaviour
{
    CancellationTokenSource _cts;

    void Awake()
    {
        _cts = new CancellationTokenSource();
        WatchSomethingAsync(_cts.Token).Forget();
    }

    async UniTask WatchSomethingAsync(CancellationToken token)
    {
        while (!token.IsCancellationRequested)
        {
            // 반복 검사
            await UniTask.Delay(1000, cancellationToken: token);
            Debug.Log("감시 중...");
        }
    }

    void OnDestroy()
    {
        // ① 토큰 취소
        _cts.Cancel();
        // ② CTS 객체 해제
        _cts.Dispose();
    }
}

private CancellationTokenSource _cts;

    private void OnEnable()
    {
        _cts = new CancellationTokenSource();
        StartAutoReturn(_cts.Token).Forget();
    }

    private void OnDisable()
    {
        _cts?.Cancel();
        _cts?.Dispose();
        _cts = null;
    }

    private async UniTaskVoid StartAutoReturn(CancellationToken token)
    {
        try
        {
            await UniTask.Delay(1000, cancellationToken: token);
            ReturnToPool(); // ex: gameObject.SetActive(false);
        }
        catch (OperationCanceledException)
        {
            // 무시해도 됨
        }
    }

    private void ReturnToPool()
    {
        gameObject.SetActive(false); // 또는 풀 시스템에 따라 반환
    }
}

버튼 클릭 이벤트 연결 & 해제 예제

public class UIButtonHandler : MonoBehaviour
{
    [SerializeField] Button _btn;
    private CancellationTokenSource _cts;

    void Awake()
    {
        _cts = new CancellationTokenSource();

        // 버튼 클릭을 비동기로 처리 (UniTask 3.x 이상)
        _btn.OnClickAsync(cancelToken: _cts.Token)
            .ContinueWith(_ => Debug.Log("버튼 클릭됨"))
            .Forget();
    }

    void OnDestroy()
    {
        // 클릭 대기 취소 및 해제
        _cts.Cancel();
        _cts.Dispose();
    }
}

Scene 전환 시 주의할 점

GetCancellationTokenOnDestroy로 자동 취소

public class SceneSafeLoader : MonoBehaviour
{
    async UniTaskVoid Start()
    {
        try
        {
            // 씬 전환으로 이 오브젝트가 파괴되면 이 토큰이 Cancel 돼요.
            await LoadHeavyData(this.GetCancellationTokenOnDestroy());
            Debug.Log("로딩 완료!");
        }
        catch (OperationCanceledException)
        {
            Debug.Log("씬 전환으로 로딩 취소됨");
        }
    }

    async UniTask LoadHeavyData(CancellationToken token)
    {
        // 예: 긴 지연이나 웹 요청
        await UniTask.Delay(TimeSpan.FromSeconds(10), cancellationToken: token);
        // ... 추가 작업
    }
}