주녘공부일지

[Unity] Coroutine & UniTask ( Coroutine 대체 ) 본문

GameEngine/UnityEngine - Class

[Unity] Coroutine & UniTask ( Coroutine 대체 )

주녘 2023. 9. 5. 17:40
728x90

0. MonoBehaviour LifeCycle

https://godgjwnsgur7.tistory.com/93

 

[Unity] MonoBehaviour 생명주기 (Life Cycle)

1. Initialization, Editor - Awake() : 프리팹 인스턴스화 직후에 호출 (스크립트 활성화) - OnEnalbe() : 오브젝트가 활성화된 직후에 호출 - Reset() : Reset 명령 혹은 스크립트 - Start() : 활성화된 후 첫 프레임

godgjwnsgur7.tistory.com

1. Coroutine

UnityEngine에서 지원하는 비선점형 멀티테스킹 시스템 (싱글 쓰레드)

- 마치 일시정지를 하듯, 원하는 시점에서 함수의 상태를 저장/복원 가능

 -> 원하는 시점에 병렬처리처럼 직렬처리할 수 있음

using System.Collections;
using UnityEngine;

public class TestClass : MonoBehaviour
{
    private IEnumerator ITestCoroutine(float delayTime)
    {
        float currTime = 0.0f;

        while (currTime < delayTime)
        {
            currTime += Time.deltaTime;

            // Update 주기 종료 후 호출
            yield return null;
        }

        // 지정한 시간 이후 & Update 주기 이후 호출
        yield return new WaitForSeconds(delayTime);

        // Time.timeScale의 영향을 받지 않는 절대적인 시간 이후 호출
        yield return new WaitForSecondsRealtime(delayTime);

        // 지정한 함수가 True를 리턴할 때까지 대기 (Update 주기 종료된 후 조건 체크)
        yield return new WaitUntil(() => delayTime < currTime);

        // FixedUpdate 주기가 종료된 후 호출
        yield return new WaitForFixedUpdate();

        // 프레임이 종료된 후 호출 (OnGUI 종료 후)
        yield return new WaitForEndOfFrame();

        ...
        
        // 코루틴 중단
        yield break;
    }
}

2. UniTask

- Coroutine을 대체할 수 있으며, return 값을 가질 수 있음 ( UniTask<T> )

- WhenAll, WhenAny 등의 내장 메서드 제공

- Zero Allocation 기능으로 성능 향상 ( 메모리 할당을 최소화 ->  코루틴은 메모리 할당이 필요 / new )

- CancellationTokenSource 클래스를 통한 취소 토큰 활용 가능

- 호출 시점 제어 가능 - 기본 값 : Update 주기 ( 매개변수로 enum PlayerLoopTiming 전달 가능 )

 

1) Coroutine <-> UniTask

 

Coroutine UniTask
yield return null await UniTask.Yield
yield return new WaitForSeconds
yield return new WaitForSecondsRealtime
await UniTask.Delay
yield return WaitUntil await UniTask.WaitUntil
yield new WaitForFixedUpdate
await UniTask.WaitForFixedUpdate
yield return WaitForEndOfFrame
await UniTask.WaitForEndOfFrame

 

using Cysharp.Threading.Tasks;
using UnityEngine;

public class TestClass : MonoBehaviour
{
    private CancellationTokenSource cts;

    private void OnEnable()
    {
        cts = new CancellationTokenSource(); // 중단조건 토큰
        AsyncTestUniTaskVoid().Forget(); // UniTask 메서드 실행
    }
    
    protected virtual void OnDisable()
    {
        cts?.Cancel(); // 토큰을 통해 메서드 종료
        cts?.Dispose(); // 사용하는 모든 리소스 해제
    }

    // UniTaskVoid
    private async UniTaskVoid AsyncTestUniTaskVoid(float delayTime)
    {
        float currTime = 0.0f;

        while (currTime < delayTime)
        {
            currTime += Time.deltaTime;

            await UniTask.Yield(PlayerLoopTiming.Update, cancellationToken: cts.Token);
        }
        
        await UniTask.Delay(TimeSpan.FromSeconds(delayTime), 
        	ignoreTimeScale: false, PlayerLoopTiming.Update, cancellationToken: cts.Token);

        await UniTask.WaitUntil(() => delayTime < currTime, 
        	PlayerLoopTiming.Update, cancellationToken: cts.Token);
        
        // Touple 값 받기
        var (google, bing, yahoo) = await UniTask.WhenAll(task1, task2, task3);

        await UniTask.WaitForFixedUpdate(cancellationToken: cts.Token);

        await UniTask.WaitForEndOfFrame(cancellationToken: cts.Token);

        ...

        // UniTask 중단 조건 : 오브젝트 파괴 (취소 토큰)
        var _token = this.GetCancellationTokenOnDestroy();
        await UniTask.Delay(1000, cancellationToken: _token);
    }
    
    // UniTask<T>
    private async UniTask<int> AsyncTestUniTask()
    {
        int value = 0;

        try
        {
            while(true)
            {
                ...

                await UniTask.Yield(PlayerLoopTiming.Update, cancellationToken: cts.Token);
            }
        }
        catch (Exception e)
        {
            Debug.LogError(e);
            return -1;
        }

        return value;
    }
}
namespace Cysharp.Threading.Tasks
{
    // 모노비헤이비어 생명주기 기준 타이밍 열거형
    public enum PlayerLoopTiming
    {
        Initialization,
        LastInitialization,
        EarlyUpdate,
        LastEarlyUpdate,
        FixedUpdate,
        LastFixedUpdate,
        PreUpdate,
        LastPreUpdate,
        Update,
        LastUpdate,
        PreLateUpdate,
        LastPreLateUpdate,
        PostLateUpdate,
        LastPostLateUpdate,
        TimeUpdate,
        LastTimeUpdate
    }
}

 

728x90

'GameEngine > UnityEngine - Class' 카테고리의 다른 글

[Unity] MonoBehaviour Life Cycle (생명주기)  (0) 2023.09.05
[Unity] Animation Blending  (0) 2022.03.23
[Unity] StateMachineBehaviour  (0) 2022.03.23
[Unity3D] Camera  (0) 2022.03.01
[Unity3D] Physics.Raycast (+LayerMask)  (0) 2022.02.24