2023.02.24 - [게임을 만들자/Unity] - 1. UniRx 시작, Subject와 ReactiveProperty
2023.03.22 - [게임을 만들자/Unity] - 2. UniRx, Observable 메소드
2023.08.25 - [게임을 만들자/Unity] - 4. UniRx, 메시지 병합(Merge, CombineLastest, Concat)
- UniRx에서는, 스트림으로 전달된 메시지를 변형하거나, 필터링 하는 등의 함수를 제공한다. 이 함수들은 C#의 Linq함수와 사용법이 비슷하다. 예를 들어 Select는 메시지를 변경하고, Where는 메시지는 필터링하는데, Linq함수의 Select/Where와 매우 흡사하다.
- Select
- 메시지를 변경한다.
heroModel.DiffHp //hp 변화량. ReactiveProperty<int> DiffHp .Select(_diff => _diff > 0) // diff값이 0 이상이면 true, 아니면 false로 메시지 전달 .Subscribe(_result => { //_result는 int가 아닌 boolean값 }.AddTo(this)
- 위 코드에서 _diff값은 int타입인데 이것을 boolean타입으로 변환한다.
- Subscribe에서 전달된 메시지(_result)는 boolean타입이다.
- Where
- 메시지를 필터링한다.
heroModel.Level //영웅 레벨. .Where(_level => _level >= 10) //레벨이 10이상인 경우만 처리 .Subscribe(_level => { //10 이상의 값만 전달 된다. }.AddTo(this)
- 위 코드는 영웅 레벨이 변경될 때마다 메시지를 전달하지만, Where문으로 레벨이 10이상일 경우만 처리하는 코드이다. 레벨이 3일 경우, Where까지 실행하고, Subscribe 코드는 동작하지 않는다.
- Skip
- 구독 후, 전달된 메시지를 N회 무시한다.
heroModel.Level .Skip(1) .Subscribe(_level =>{}) .AddTo(this)
- 위 코드의 Level은 ReactiveProperty만들었을 경우, Subscribe 시 현재 값을 메시지로 받는다. 하지만 어떤 경우엔, 처음 메시지를 넘기고 싶을 때가 있다. 위 코는 맨 처음 구독 시 받는 메시지를 무시하고, 그 다음 레벨 값 부터 Subscribe의 Action이 실행된다.
- Take
- N개의 메시지만 받는다. N개 메시지 후, 종료된다(OnCompleted).
public class UiClip { //클립 ui가 닫힐 때, HideSubject.OnNext()호출 private readonly Subject<Unit> HideSubject = new(); public IObservable<Unit> HideObservable => HideSubject; } //HideObservable은 IObservable<Unit> 타입이다. //클립 ui가 닫힐 때까지 기다림 await clip.HideObservable.Take(1).ToTask(); //닫히고 난 후 처리 ...
- ToTask()함수와 함께 사용
- ToTask는 IObservable를 Task객체로 반환해준다. 마지막 값이나, 스트림 중의 Exception을 반환한다.
- 위 코드는 1개의 메시지를 기다리는 코드이다. 비동기 코드로 특정 메시지를 기다릴 때 사용하기 좋다. 위 코드에서는 Clip(게임 상에서 메시지 팝업같은 것) Ui코드에 Subject<Unit> 멤버 변수를 두고, 해당 클립이 닫힐 때, OnNext()함수를 호출해 메시지를 전달한다. 클립이 닫히는 이벤트를 가다리는 곳에서, HideObservable의 Take함수를 호출하고, Take함수의 리턴값(IObservable<T>)을 이용해 Task로 바꿔 await한다.
- Throttle / ThrottleFrame
- 메시지 중복을 방지하기 위해, 일정 시간 혹은 간격 동안 받은 메시지 중 마지막 메시지를 전달한다.
- 아래 코드에서 OnClickSubject를 구독하며, 1초에 한 번씩 메시지를 전달한다.
- 이전 메시지가 전달된 이후 1초가 지나지 않으면, 새로운 메시지를 전달하지 않고 이전 메시지를 유지한다.
//Observable의 Throttle함수 예제 public class ThrottleTest : MonoBehaviour { private readonly Subject<Unit> OnClickSubject = new(); private void Awake() { //버튼 클릭 시, Subject에 메시지 전달 GetComponent<Button>() .OnClickAsObservable() .Subscribe(_ => OnClickSubject.OnNext()) .AddTo(this); //Subject를 구독하며, 1초에 한번씩 메시지 전달 OnClickSubject .Throttle(TimeSpan.FromSeconds(1)) .Subscribe(_ => Debug.Log("Click")) .AddTo(this); } }
- 메시지를 병합하는 경우, 한 프레임 내에 같은 메시지가 중복 전달되는 경우가 많다. 이때 ThrottleFrame(1) 설정해, 마지막 메시지만 처리하도록 하여 성능 저하를 막는다.
- Distinct
- 중복 값을 무시한다. 한번 통과했던 값은 무시한다.
- DistinctUntilChanged
- 값이 변할 때만 메시지를 전달한다.
//현재 ui상의 탭 선택한 값 currentTabState .DistinctUntilChanged() .Subscribe(_selectedTab => { //선택한 탭이 변경 되었을 때만 동작 }).Add(this);
- 위 코드는 ui상에서 많이 쓰이는 탭 페이지를 구현했을 때의 예이다. 탭이 변경된 경우의 행동을 정의한다.
'게임을 만들자 > Unity' 카테고리의 다른 글
Unity, ScrollRect verticalNormalizedPosition 조절 (0) | 2023.11.07 |
---|---|
4. UniRx, 메시지 병합(Merge, CombineLastest, Concat) (0) | 2023.08.25 |
Unity Android Pip (0) | 2023.07.12 |
2. UniRx, Observable 메소드 (0) | 2023.03.22 |
1. UniRx 시작, Subject와 ReactiveProperty (0) | 2023.02.24 |