2023.02.24 - [게임을 만들자/Unity] - 1. UniRx 시작, Subject와 ReactiveProperty
2023.08.14 - [게임을 만들자/Unity] - 3. UniRx, 메시지 제어(Select, Where..)
2023.08.25 - [게임을 만들자/Unity] - 4. UniRx, 메시지 병합(Merge, CombineLastest, Concat)
- Observable메소드
- IObservable객체, 즉 구독 가능한 객체를 만든다.
- Subject나 ReactivePropery 외에, 프레임워크에서 제공하는 기능들을 구독해야 하는 경우들이 있다. 예를들어 GameObject의 Update, 코루틴 등, 다양한 상황을 구독하고 싶을 때가 있다. Observable클래스에서 이러한 것들을 가능하게 해주는 메소드를 제공하고 있다.
- Observable.Create
- 메시지를 발행하는 IObservable 객체를 직접 생성한다.
Observable.Create<int>(_observer => { for (var i = 0; i < 10; i++) { _observer.OnNext(i); } return Disposable.Create(() => { //dispose 시 처리 }); }).Subscribe(_value => { Debug.Log(_value); }).AddTo(this);
- 어떤 함수의 callback결과를 받고 싶을 때 사용한다.
public async Task ShowInquiry() { //showInquiry 함수의 콜백을 기다린다. var result = await Observable.Create<ResultAPI>(_observer => { AuthV4.showInquiry(_ => { //showInquiry의 람다 콜백발생 시, OnNext호출 _observer.OnNext(_); }); return Disposable.Empty; }).Take(1).ToTask(); //OnNext발생 때 까지(take 1이므로 한번만), await한다. if (result.isSuccess()) { //결과 처리 } }
- Observable.Return
- 메시지를 1개 발행한다. 구독 즉시 메시지를 발행.
Subject<bool> OnHeroDead = new(); var observableHeroDead = Observable.Return(false).Concat(OnHeroDead);
- Subject같은 경우, 구독 시에 메시지를 발행하지 않는다. 만약 구독 시 메시지를 발행하고 싶은 경우 사용한다. 위 코드에서 [observableHeroDead] 구독 시, false값을 발행하고, [OnHeroDead]의 메시지 발행을 기다린다.
- Observable.FromEvent
- event로부터 IObservable객체를 만든다.
//이벤트 생성 Action<int> testEvent = _i => { Debug.Log($"testEvent {_i}"); }; //이벤트로 IObservable객체를 만든다. var testObservable = Observable.FromEvent<int>( _h => testEvent += _h, _h => testEvent -= _h); //이벤트로 만든 IObservable 객체를 구독한다. testObservable.Subscribe(_i => { Debug.Log($"testEvent in Subscribe {_i}"); }).AddTo(this) //이벤트 발생 결과 //testEvent 10 //testEvent in Subscribe 10 testEvent(10);
- 인자가 여러 개 있는 경우
public delegate void OnComplate (int _value,string _msg); public event OnComplate onComplateEvent; Observable.FromEvent<OnComplate,(int, string)> h => h.Invoke, //h => (_value,_msg) => h (_value,_msg) 이렇게도 가능 h => onComplateEvent += h, h => onComplateEvent -= h, .Subscribe (_ => {...}))
- 위 코드처럼 이벤트 하나를 구독하는 것은 크게 의미가 없어 보인다.
- 하지만 여러 이벤트를 조합해 사용하는 경우(Merge, Combine, Zip, Concat등) 유용할 듯 하다.
- 예를 들어, 두 개의 이벤트가 모두 발생할 때까지 기다려야 하는 경우(CombineLastest), 두 이벤트 중 하나라도 발생하는 경우(Merge)
- Observable.Timer
- 일정 시간 후, 메시지를 발행한다. 인자가 1개인 경우, 메시지를 한번 발행한다. 인자가 2개인 경우 2번째 인자 시간마다, 주기적으로 메시지를 발행한다.
- Observable.TimerFrame는 일정 프레임 후 메시지를 발행한다. 사용방법은 Timer와 같다.
//10초 후 메시지 한개 발행 Observable.Timer(TimeSpan.FromSeconds(10)) .Subscribe(_ => {...}) .AddTo(this); //10초 후 메시지를 한개 발행하고, 그 후 1초마다 주기적으로 메시지를 발행 Observable.Timer(TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(1)) .Subscribe(_ => {...}) .AddTo(this);
- Observable.Interval
- 일정 시간 간격으로 실행
- Interval 함수는 메인스레드에서 동작하므로 Thread-Safe하다
- Observable.Timer와 동일한 기능.
//x값은 0부터 시작해 점차 증가한다. 아래 코드는 1씩 Observable.Interval(TimeSpan.FromSeconds(1)) .Subscribe(x => Debug.Log(x));
- Observable.FromCoroutine
- 코루틴을 Observable로 변환한 후 사용.
- dispose()를 사용하여, 중단할 수 있다.(CompositDisposal 이용)
CompositeDisposable compositeDisposable = new new(); void TestCoroutine() { //기존에 등록된 구독을 취소 compositeDisposable.Clear(); Observable.FromCoroutine<int>(_observer => TestCoroutine(_observer)) .Subscribe(_ => { Debug.Log(_); //TestCoroutine에서 OnNext할 때마다 실행됨 }) .AddTo(compositeDisposable); } IEnumerator TestCoroutine(IObserver<int> _observer) { var i = 0; while (i < 100) { //do //... yield return new WaitForSeconds(1); _observer.OnNext(i++); } _observer.OnCompleted(); }
- Observable.EveryUpdate
- GameObject의 Update마다 메시지를 발행한다.
Observable.EveryUpdate() .Where(_ => Input.GetKeyDown(KeyCode.Space)) .Subscribe(_ => Debug.Log("Space Key Down"));
- ObserveEveryValueChanged
- 클래스의 멤버 변수 값이 변경 되는 경우, 메시지를 발행한다.
private CharacterController _controller; private void Start() { _controller = GetComponent<CharacterController>(); _controller.ObserveEveryValueChanged(x => x.isGrounded) .Subscribe(isGrounded => Debug.Log($"isGrounded changed to {isGrounded}")); }
- 위 코드에서 CharacterController 클래스의 isGrounded멤버 값이 바뀌는 경우 메시지를 발행된다.
- 내부적으로, 매 루프 마다 값을 체크한다.
- 파라미터로 Update, FixedUpdate, EndOfFrame를 선택할 수 있다.
- 내부적으로, 매 루프 마다 값을 체크한다.
'게임을 만들자 > Unity' 카테고리의 다른 글
3. UniRx, 메시지 제어(Select, Where..) (0) | 2023.08.14 |
---|---|
Unity Android Pip (0) | 2023.07.12 |
1. UniRx 시작, Subject와 ReactiveProperty (0) | 2023.02.24 |
C#, 기기 시간과 인터넷 표준시간 비교하기 (0) | 2022.05.25 |
Unity, Tilemap 검은 선 없애기. (0) | 2021.04.19 |