코루틴과 UniRX는 상호 보완적으로 사용될 수 있다.
코루틴을 Observable로 변환하고, Observable을 코루틴으로 변환하며 혼용 사용이 가능하다.
1. 코루틴을 스트림으로 변환하기
- 복잡한 처리를 코루틴에 숨기고 외부에서는 Observable로서 취급하는 것이 가능하다.
- Cold 라서 Subscribe 될 때마다 새롭게 코루틴이 생성되고 시작한다.
1-1) Observable.FromCoroutine
- 코루틴의 종료시간까지 대기하다, yield 된 시점에 OnCompleted()메시지가 호출된다.
- 첫 번째 인수로는 코루틴을 취하고,
두 번째 인수로는 yield시점에 OnNext()메시지를 발행하는지 여부 (기본 false이며, OnCompleted 직전에 한 번 발급)
public static IObservable<Unit> FromCoroutine(Func<IEnumerator> coroutine, bool publishEveryYield = false)
public static IObservable<Unit> FromCoroutine(Func<CancellationToken, IEnumerator> coroutine, bool publishEveryYield = false)
- 사용 예시 : 코루틴이 종료되는 2초 후 문자열 출력
public void Start()
{
Observable.FromCoroutine(ACoroutine, false)
.Subscribe(_ => Debug.Log("OnNext"),
() => Debug.Log("OnCompleted"));
}
private IEnumerator ACoroutine()
{
Debug.Log("코루틴 시작");
yield return new WaitForSeconds(2f);
Debug.Log("코루틴 끝");
}
- publishEveryYield = true 일 때의 결과 ( 매 yield 마다 OnNext가 발행 )
1-2) Observable.FromCoroutineValue<T>
- 코루틴의 yield return 값을 OnNext 메시지로 받는다.
- 리턴된 값이 형식 인수와 맞지 않으면 오류가 발생한다. (형 변환)
private void Start()
{
Observable.FromCoroutineValue<string>(MyCoroutine)
.Subscribe((n) => Debug.Log(n));
}
public IEnumerator MyCoroutine()
{
while(true)
{
yield return new WaitForSeconds(1f);
yield return "리턴";
}
}
1-3) 코루틴에서 직접 메시지를 발행
코루틴에 IObserver<T>를 넘겨서 코루틴 내부에서 메시지를 발행할 수 있다.
- FromCoroutine의 매개변수는 IObserver<T>를 매개변수로 가지고, IEnumerator를 반환형으로 가지는 Func
(즉 IObserver<T>를 매개 변수로 가진 코루틴을 호출하는 람다식)
public static IObservable<T> FromCoroutine<T>(Func<IObserver<T>, IEnumerator> coroutine)
public static IObservable<T> FromCoroutine<T>(Func<IObserver<T>, CancellationToken, IEnumerator> coroutine)
- 코루틴 내에서는 매개변수로 받은 IObserver<T> 객체를 통해 원하는 타이밍에
OnNext(T)와 OnCompleted()등을 호출하여 메시지를 보낼 수 있다.
public class MyClass
{
public void Start()
{
Observable.FromCoroutine<int>(observer => MyCoroutine(observer, 0, 10))
.Subscribe(count => Debug.Log(count));
}
private IEnumerator MyCoroutine(IObserver<int> observer, int startCount, int endCount)
{
int count = startCount;
while (true)
{
yield return new WaitForSeconds(0.1f);
observer.OnNext(++count);
if (count >= endCount)
observer.OnCompleted();
}
}
}
2. 스트림을 코루틴으로 변환하기
- StartAsCoroutine를 사용하여 IObservable을 코루틴으로 변환할 수 있다.
- 5.3 버전부터는 StartAsCoroutine()을 ToYieldInstruction으로 사용할 수도 있다.
public static Coroutine StartAsCoroutine<T>(this IObservable<T> source, CancellationToken cancel = default(CancellationToken))
public static Coroutine StartAsCoroutine<T>(this IObservable<T> source, Action<T> onResult, CancellationToken cancel = default(CancellationToken))
public static Coroutine StartAsCoroutine<T>(this IObservable<T> source, Action<Exception> onError, CancellationToken cancel = default(CancellationToken))
public static Coroutine StartAsCoroutine<T>(this IObservable<T> source, Action<T> onResult, Action<Exception> onError, CancellationToken cancel = default(CancellationToken))
- OnCompleted를 호출할 때까지 yield return null을 계속 반복한다.
- StartAsCoroutine에 전달된 함수는 OnCompleted를 호출할 때에 한 번만 실행되고 마지막 OnNext 값이 전달된다.
private void Start()
{
StartCoroutine(MyCoroutine());
}
public IEnumerator MyCoroutine()
{
Debug.Log("코루틴 시작");
int result = 0;
yield return Observable.Range(1, 10).StartAsCoroutine(n => result = n);
Debug.Log($"결과값 :{result}");
}
'🌍 Unity 연구 > UniRX' 카테고리의 다른 글
UniRX 배우기 7) MessageBroker 전역 옵저버 이벤트시스템 (0) | 2021.09.06 |
---|---|
UniRX 배우기 6) UniRX 오퍼레이터 (0) | 2021.04.30 |
UniRX 배우기 4) Hot, Cold Observable (0) | 2021.04.29 |
UniRX 배우기 3) 스트림의 구독과 종료시점 (0) | 2021.04.26 |
UniRX 배우기 2) Observable 객체 생성하기 (0) | 2021.04.25 |