공부블로그

[공부 블로그] Unitask를 사용해보자

bimtaeur30 2025. 12. 1. 09:45

안녕하세요.

오늘은 동아리 졸업생 선배님 맨토링 활동에서 선배님이 알려주신 Unitask를 사용해보도록 하겠습니다.

 

직접 적용시켜보기 전 Unitask에 대해 한번 더 알아보겠습니다.

Unitask란? 유니티 엔진에서 비동기 작업을 더욱 효과적으로 처리하기 위해 사용하는 외부 라이브러리입니다.

 

어떤 점에서 코루틴보다 더욱 효과적으로 비동기 작업을 처리할 수 있는것일까요?

Unitask는 코루틴보다 우선 성능적으로 뛰어납니다. 오버헤드를 줄이고, 무엇보다 가비지 할당을 최소화시켜준다는 장점이 있습니다. 또한, 유니티의 메인 스레드와 렌더링 루프에 맞게 최적화되어있어, 일반 .NET 의 Task보다 유니티 환경에서 더 효과적입니다.

 

이제 직접 적용시켜보겠습니다.

저는 현재 CameraEffectManager에서 코루틴 방식으로 작동하고 있는 코드를 Unitask를 사용하는 코드로 바꿔보려합니다.

다음은 CameraEffectManager에 있는 기능중 하나인 CameraZoom 입니다.

 

코루틴을 캐싱해두고 새로운 코루틴을 실행할때면 캐싱해둔 코루틴을 중지시키고 새로운 코루틴을 플레이합니다.

[SerializeField] private Camera _camera;
private Coroutine _zoomCoroutine;
private Coroutine _moveCoroutine;

public void CameraZoom(float Amount, float Time)
{
    if (_zoomCoroutine != null)
    {
        StopCoroutine(_zoomCoroutine);
    }
    _zoomCoroutine = StartCoroutine(ZoomCoroutine(Amount, Time));
}

private IEnumerator ZoomCoroutine(float amount, float duration)
{
    float startSize = _camera.orthographicSize;
    float targetSize = amount;
    float t = 0f;

    while (t < 1f)
    {
        t += Time.deltaTime / duration;
        _camera.orthographicSize = Mathf.Lerp(startSize, targetSize, t);
        yield return null;
    }

    _camera.orthographicSize = targetSize;
}

 

이제 이 코드를 Unitask를 사용하는 코드로 변환시켜보겠습니다.

주요 변경사항은 다음과 같습니다.

 

기존 Corutine을 CancellationTokenSource로 교체하여 토큰 기반으로 기존 UniTask를 취소하고 플레이할 수 있도록 했습니다.
또한 StartCorutine도 사라지게 되어 성능이 향상되었습니다.

await UniTask.Yield를 통해 한 프레임씩 while이 반복되도록 해주었습니다.

[SerializeField] private Camera _camera;
private CancellationTokenSource _zoomCoroutine;
private CancellationTokenSource _moveCoroutine;

public void CameraZoom(float Amount, float Time)
{
    _zoomCoroutine?.Cancel();
    _zoomCoroutine?.Dispose();
    _zoomCoroutine = new CancellationTokenSource();

    ZoomCoroutine(Amount, Time, _zoomCoroutine.Token).Forget();
}

private async UniTask ZoomCoroutine(float amount, float duration, CancellationToken token)
{
    float startSize = _camera.orthographicSize;
    float targetSize = amount;
    float t = 0f;

    while (t < 1f)
    {
        _zoomCoroutine.Token.ThrowIfCancellationRequested();

        t += Time.deltaTime / duration;
        _camera.orthographicSize = Mathf.Lerp(startSize, targetSize, t);

        await UniTask.Yield(PlayerLoopTiming.Update);
    }

    _camera.orthographicSize = targetSize;
}

 

앞으로 코루틴 대신 UniTask를 애용해보고 완전하게 익힐 수 있도록 노력하겠습니다.

감사합니다.