Unity에서 Reactive Programming을 쉽게 구현할 수 있게 만든 라이브러리이다. .NET에도 Rx 라이브러리가 있지만 Unity에 최적화되어 있지 않다. UniRx는 Unity에 최적화되어 만들어졌다.
데이터 또는 이벤트의 변경이 발생하면 이에 반응해 처리하는 프로그래밍 기법이다.
일반적으로 유니티의 네트워크 운영은 WWW와 코루틴을 사용해야 한다. 그렇지만 아래와 같은 이유로 코루틴을 사용하는 것은 비동기 연산에 좋은 방법이 아니다
스트림(Stream)을 생성한다.
오퍼레이터를 사용하여 스트림을 가공한다.
가공된 스트림을 구독하여 사용한다.
ISubject 클래스는 IObserver와 IObservable 인터페이스를 구현하고 있다.
namespace UniRx
{
public interface ISubject<TSource, TResult> : IObserver<TSource>, IObservable<TResult>
{
}
public interface ISubject<T> : ISubject<T, T>, IObserver<T>, IObservable<T>
{
}
}
IObserver와 IObservable에는 각각 OnCompleted, OnError, OnNext와 Subscribe 함수가 정의되어 있다.
namespace System
{
public interface IObserver<in T>
{
void OnCompleted();
void OnError(Exception error);
void OnNext(T value);
}
}
namespace System
{
public interface IObservable<out T>
{
IDisposable Subscribe(IObserver<T> observer);
}
}
이벤트를 받기 위해 구독하는 함수 이벤트 발생시 실행할 로직을 등록한다.
private Subject<string> subject = new Subject<string>();
subject.Subscribe(x => Debug.Log(x));
구독자에게 이벤트를 통지한다.
private Subject<string> subject = new Subject<string>();
subject.Subscribe(x => Debug.Log(x));
...
subject.OnNext("Hello");
// Result
// Hello
스트림이 완료되었을때 통지된다. OnComplete이 통지되면 해당 스트림은 종료되며 종료된 Subject는 재사용이 불가능하다. 종료된 Subject에 Subscribe를 호출할 경우 OnComplete가 실행된다.
private Subject<string> subject = new Subject<string>();
subject.Subscribe(x => Debug.Log(x), () => Debug.Log("Complete"));
...
subject.OnNext("Hello");
subject.OnComplete();
subject.OnNext("World!");
subject.Subscribe(x => Debug.Log(x), () => Debug.Log("Complete"));
subject.OnNext("Bye");
// Result
// Hello
// Complete
// Complete
스트림 진행중 오류가 발생했을 때 통지된다. 에러 처리가 필요할 경우 작성하고 생략도 가능하다. OnError가 통지될 경우에도 해당 스트림은 종료된다.
private Subject<string> subject = new Subject<string>();
subject.Select(x => {
if (x.Length > 5) {
throw new Exception("String Length is more than 5");
}
return x;
}).Subscribe(x => { Debug.Log(x); },
ex => Debug.Log("Error : " + ex.Message),
() => Debug.Log("Complete"));
subject.OnNext("ABCD");
subject.OnNext("EFGHIJ");
// result
// ABCD
// Error : String Length is more than 5
IObservable 인터페이스의 Subscribe 함수는 IDisposable를 반환하기 때문에 Dispose 함수를 이용하여 메모리 해제를 할 수 있다. 이때 OnComplete는 실행되지 않는다.
private Subject<string> subject = new Subject<string>();
subject.Subscribe(x => Debug.Log(x), () => Debug.Log("Complete"));
subject.OnNext("ABC");
subject.OnNext("DEF");
subject.Dispose();
subject.OnNext("GHI"); // ObjectDisposedException 예외 발생
// result
// ABC
// DEF
OnComplete는 모든 구독 상태를 완료시키지만 Dispose를 이용하면 해당 구독만 해제할 수 있다.
private Subject<string> subject = new Subject<string>();
var disposable_1 = subject.Subscribe(x => Debug.Log(x), () => Debug.Log("Complete"));
var disposable_2 = subject.Subscribe(x => Debug.Log(x), () => Debug.Log("Complete"));
subject.OnNext("ABC");
subject.OnNext("DEF");
disposable_1.Dispose();
subject.OnNext("GHI");
subject.OnCompleted();
// result
// ABC
// ABC
// DEF
// DEF
// GHI
// Complete