[TIL] Unity 통합과 비동기

muchan
muchan
∙∙조회 9

R3.Unity

  • 프레임 스트림 - Observable.EveryUpdate(): 매 프레임 발행하는 전역 스트림. Update() 함수의 리액티브 대응물.
  • 타임/프레임 프로바이더 - Timer/Interval/Debounce 같은 시간 연산자가 내부에서 쓰는 “시계”를 유니티 것으로 교체함. R3.Unity가 시작 시 자동으로 기본값을 등록하므로(UnityTimeProvider.Update / UnityFrameProvider.Update) 아무 설정 없이 유니티 시간 기준으로 동작함.
  • 변형 프로바이더 - timeScale 무시(UnityTimeProvider.UpdateIgnoreTimeScale) 등이 필요하면 연산자의 TimeProvider 인자로 골라 끼움. 일시정지 중에도 돌아야 하는 UI 타이머 같은 곳에서 씀.
  • 프레임 단위 연산자 - DelayFrame, DebounceFrame, ThrottleFirstFrame처럼 시간 대신 프레임 수로 동작하는 변형이 있음. “다음 프레임에”, “3프레임 모아서” 같은 게임 특유의 요구와 맞음.
  • 그 외 함께 쓰는 것들 - AddTo(구독 수명 관리), SerializableReactiveProperty(인스펙터에 노출되는 ReactiveProperty), uGUI 확장(아래), Window > Observable Tracker(구독 추적 창).
csharp
// 매 프레임 입력 검사 - Update() 함수 없이. 전역 스트림이므로 AddTo 필수!
Observable.EveryUpdate()
    .Where(_ => Keyboard.current != null && Keyboard.current.spaceKey.wasPressedThisFrame)
    .Subscribe(_ => Jump())
    .AddTo(this);

Update() 함수와 뭐가 다른가 - 함수 하나에 입력·타이머·상태 검사가 섞이는 대신, 관심사마다 독립된 파이프라인으로 분리되고 각자 수명을 가짐. 다만 매 프레임 폴링 자체가 사라지는 건 아님 - 표현이 정리되는 것임.

uGUI 이벤트를 스트림으로

  • ThrottleFirst: 쿨다운
  • Chunk: 연타
  • Merge: 합성

onClick.AddListener와 다르게 이벤트가 스트림 된 것

async/await 통합

Observable -> await: 한번의 사건 기다리기

csharp
// "다음 클릭 한 번"을 await - 컷씬 진행, 튜토리얼 "아무 키나 누르세요"
await m_Button.OnClickAsObservable().FirstAsync(destroyCancellationToken);

// 스트림이 완료될 때까지 대기
await someStream.WaitAsync(ct);

비동기 작업 -> Observable: 단발 작업을 스트림으로

csharp
// 비동기 함수 하나를 Observable로 - 결과가 스트림으로 흘러 연산자를 이어 붙일 수 있다
Observable.FromAsync(async ct => await LoadPlayerDataAsync(ct))
    .Subscribe(data => Apply(data))
    .AddTo(this);

SubscribeAwait - 스트림 처리 자체가 비동기일 때 (SubscribeAwait)

csharp
// 평범한 async UniTask 메서드 - 속엔 R3가 없고, R3가 이걸 바깥에서 합성한다
async UniTask LoadAsync(CancellationToken ct)
{
    await UniTask.Delay(TimeSpan.FromSeconds(1.5), cancellationToken: ct);
}

m_LoadButton.OnClickAsObservable()
    .SubscribeAwait(async (_, ct) =>
    {
        await LoadAsync(ct);          // ct: 구독 해제(오브젝트 파괴) 시 자동 취소
    }, AwaitOperation.Drop)           // 처리 중 들어온 클릭은 버림 - 연타 방지
    .AddTo(this);

이벤트가 오면 어떻게 처리할지 -> AwaitOperation 인자

AwaitOperation처리 중 새 이벤트가 오면용례
Sequential줄 세워 순서대로 처리(기본)순서 보장이 필요한 큐
Drop버림저장/로드 버튼 연타 방지
Switch진행 중인 걸 취소하고 갈아탐최신 검색어만 유효한 자동완성
Parallel동시에 처리독립적인 다발 작업