⚙️ Programming/C# & Unity

[Unity] UniRX - 5 Operator

Sugar0810 2023. 1. 16. 16:44

오퍼레이터(Operator)?

UniRx에서 Observable을 통해 관찰 대상이 결정되면 스트림에 값들을 흘려보내게 된다.

 

이 값들은 상황과 필요에 따라 기본값이 아닌 조작이나 필터링 등을 거쳐서 실제 내가 필요한 값들로 바꿔야 구독자에서 바로 사용할 수 있는 경우가 대부분일 것이다.

 

이 일련의 상황을 간단하게 그림으로 표현해 보면 아래와 같다.

이 과정에서 어떤 값을 사용할지 선택(Select) 하거나 필요한 데이터 들만 필터링(Where) 하거나 한 번에 여러 개의 데이터를 모아서(Buffer) 전달하거나 특정 상황 전까지는 데이터를 무시(Skip) 하는 등의 여러 조작이 필요하다.

이런 상황에서 데이터를 조작하게 해주는 명령어를 Operator라고 한다.

UniRx에서는 수십 가지에 달하는 정말 다양한 오퍼레이터를 제공한다.

그중에서도 상황에 맞는 오퍼레이터를 얼마나 잘 선택하느냐가 UniRx 활용 능력의 핵심이기도 하다.

이 포스팅에선 대표적인 오퍼레이터인 WhereSelect의 사용법을 살펴본다.

 

LINQ 에도 동일한 오퍼레이터가 있기 때문에 LINQ를 사용해 본 사람은 매우 익숙할 것이다.

 

Where

  • IObservable에서 흐르는 이벤트 들 중에 필요 없는 이벤트를 걸러낼 수 있는 필터링 오퍼레이터
  • Subscribe 안에서 최종적으로 넘겨받은 데이터들을 if 구문으로 체크한 후 사용할 수도 있겠지만 Where 오퍼레이터를 사용하면 훨씬 간결하면서 가독성 높은 코드를 만들 수 있다.
// 마우스 클릭 하고 있으면 ClickMouse 를 출력
Observable.EveryUpdate()
  .Where(_ => Input.GetMouseButtonDown(0))
  .Subscribe(_ => Debug.Log("ClickMouse"));

마우스 클릭 상태 체크

 

Update 되는 매 프레임을 스트림으로 흘려보내는데 Subscribe로 전달하기 전에 Where 오퍼레이터로 체크를 하면 true 인 경우에만 전달하고 false는 걸러내 주므로 Subscribe 내에서는 오직 데이터의 처리에만 집중할 수 있다.

 

Select

  • 스트림을 변경하기 위해 사용하는 오퍼레이터
  • int 타입의 데이터를 흘려보내는 스트림에서 Select 구문을 사용하면 다음부터는 다른 타입(예를 들어 Vector3 나 string 같은..)의 데이터를 전달하게 된다.
// 마우스 클릭 하고 있으면 현재 마우스 좌표를 출력
Observable.EveryUpdate()
  .Where(_ => Input.GetMouseButtonDown(0))
  // 이 스트림은 Select 이후로는 Vector3 타입의 mousePosition 을 통지한다.
  .Select(_ => Input.mousePosition)  
  // Subscribe 에 통지되는 메세지는 Vector3
  .Subscribe(x => Debug.Log(x));

위 Where 설명을 위한 샘플 코드에 Select 구문이 추가된 코드

 

Input.GetMouseButtonDown(0)가 true 일 경우에만 다음 오퍼레이터인 Select로 전달하므로 여기에서는 마우스 버튼을 클릭하고 있음을 보장받았기 때문에 스트림에 Vector3 타입인 Input.mousePosition 값을 흘려보낸다.

 

그러면 Subscribe에서는 마우스 버튼을 누르고 있을 때만 이 Vector3 좌표를 넘겨받으므로 최종 처리만 하면 된다.

 

SelectMany

  • Select 가 기존 스트림에서 값을 바꾸는 처리를 수행하는데 비해 SelectMany는 새로운 스트림을 생성하여 본래의 스트림을 대체시킨다.
public Button button;

void Start()
{
    button.OnPointerDownAsObservable()  //button 에 Pointer Down 이벤트 발생 Observable
    	// 매 프레임 관찰하는 스트림을 새로 생성하여 대체
        .SelectMany(_ => button.UpdateAsObservable())   
        // 매 프레임 관찰하는 스트림 중에 button 의 Pointer Up 이 오면 중단
        .TakeUntil(button.OnPointerUpAsObservable())     
        .Subscribe(_ =>
        {
            Debug.Log("pressing...");   
        });
}

 


 

📚 참고사이트