// 값이 변하는 순간을 포착 private void CaptureWhenValueChanges() { // 마우스 클릭, 떼는 순간 모두 포착 this.UpdateAsObservable() .Select(_ => Input.GetMouseButton(0)) .DistinctUntilChanged() .Skip(1) // 시작하자마자 false값에 대한 판정 때문에 "Up" 호출되는 것 방지 .Subscribe(down => { if (down) { Debug.Log($"Down : {Time.frameCount}"); } else { Debug.Log($"Up : {Time.frameCount}"); } }); // 값이 false -> true로 바뀌는 순간만 포착 this.UpdateAsObservable() .Select(_ => this._boolValue) .DistinctUntilChanged() .Where(x => x) .Skip(TimeSpan.Zero) // 초기값이 true일 때 첫 프레임에 바로 호출되는 것 방지 .Subscribe(_ => Debug.Log("TRUE")); // 매 프레임, 값의 변화 포착만을 위한 간단한 구문 (위 구문을 간소화) this.ObserveEveryValueChanged(_ => this._boolValue) .Where(x => x) .Skip(TimeSpan.Zero) .Subscribe(_ => Debug.Log("TRUE 2")); }
private void CoroutineToStream() { // [1] 코루틴을 스트림으로 변환한 경우 // - 코루틴이 종료된 후에 OnNext(), OnCompleted() 호출됨 // 코루틴 변환 방법 1 TestRoutine() .ToObservable() .Subscribe(_ => Debug.Log("Next 1"), () => Debug.Log("Completed 1")); // 코루틴 변환 방법 2 Observable.FromCoroutine(TestRoutine) .Subscribe(_ => Debug.Log("Next 2")); // [2] FromCoroutineValue<T> // : 코루틴에서 정수형 yield return 값 받아 사용하기 // - 코루틴에서 yield return으로 값을 넘길 때마다 OnNext(T) 호출됨 // - 값을 넘겨주는 경우에는 프레임이 넘어가지 않음 // - WaitForSeconds(), null 등은 값을 넘겨주지 않고 프레임을 넘기는 역할만 수행 // - 타입이 다른 값을 리턴하는 경우에 InvalidCastException 발생 // - 코루틴이 종료된 후에 OnCompleted() 호출됨 Observable.FromCoroutineValue <int>(TestRoutine) .Subscribe(x => Debug.Log("Next : " + x), () => Debug.Log("Completed 3")); }
private void UpdateDifferences() { // 게임오브젝트가 활성화된 동안에만 OnNext() 통지 // 게임오브젝트가 파괴될 때 OnCompleted() this.UpdateAsObservable() .Where(_ => Input.GetMouseButtonDown(0)) .Subscribe( _ => Debug.Log("UpdateAsObservable" + this._intValue), () => Debug.Log("UpdateAsObservable Completed") ); // 대상 객체가 활성화된 동안에만 OnNext() 통지 // 대상 객체가 파괴될 때 OnCompleted() this.ObserveEveryValueChanged(_ => Input.GetMouseButton(0)) .Where(x => x) .Skip(TimeSpan.Zero) .Subscribe( _ => Debug.Log("ObserveEveryValueChanged"), () => Debug.Log("ObserveEveryValueChanged Completed") ); // 독자적 Observable.EveryUpdate() .Where(_ => Input.GetMouseButtonDown(1)) .Subscribe( _ => Debug.Log("EveryUpdate" + this._intValue), () => Debug.Log("EveryUpdate Completed") ); }
private void TestObserveValueOnEveryUpdate() { // 대상의 값을 그냥 매 프레임 조건 없이 출력 this.UpdateAsObservable() .Select(_ => this._intValue) .Subscribe(x => Debug.Log(x)); }
private void DragAndDrop() { this.OnMouseDownAsObservable() .SelectMany(_ => this.UpdateAsObservable()) .TakeUntil(this.OnMouseUpAsObservable()) .Select(_ => Input.mousePosition) .RepeatUntilDestroy(this) // Safe Repeating .Subscribe(x => Debug.Log(x)); }
private void AsyncGetFromWeb() { // Obsolete : Use UnityEngine.Networking.UnityWebRequest Instead. ObservableWWW.Get("http://google.co.kr/") .Subscribe( x => Debug.Log(x.Substring(0, 20)), // onSuccess ex => Debug.LogException(ex) // onError ); }
private void CheckDoubleClickImmediatley() { // 목표 : 두 번째 클릭을 인지하는 순간 OnNext 발생 // 제대로 감지 못하는 버그 존재 Observable.EveryUpdate().Where(_ => Input.GetMouseButtonDown(0)) .Buffer(TimeSpan.FromMilliseconds(500), 2) .Where(buffer => buffer.Count >= 2) .Subscribe(_ => Debug.Log("DoubleClicked!")); }
private void EventToStream() { MyEvent = new UnityEngine.Events.UnityEvent(); MyEvent .AsObservable() .Subscribe(_ => Debug.Log("Event Call")); MyEvent.Invoke(); MyEvent.Invoke(); }
private void EventAsStream() { var buttonStream = _targetButton.onClick.AsObservable() //.TakeUntil(_targetButton2.onClick.AsObservable()) .TakeUntilDestroy(_targetButton) .Subscribe( _ => Debug.Log("Click!"), _ => Debug.Log("Error"), () => Debug.Log("Completed") ); }
private void TestFilters() { var leftMouseDown = Observable.EveryUpdate() .Where(_ => Input.GetMouseButtonDown(0)); var rightMouseDown = Observable.EveryUpdate() .Where(_ => Input.GetMouseButtonDown(1)); //==================================================================== leftMouseDown .ThrottleFirst(TimeSpan.FromMilliseconds(1000)) //.Subscribe(_ => Debug.Log("Click"), ()=> Debug.Log("Completed")) ; leftMouseDown .Take(5) //.Subscribe(_ => Debug.Log("Click"), ()=> Debug.Log("Completed")) ; leftMouseDown .TakeUntil(rightMouseDown) //.Subscribe(_ => Debug.Log("Click"), ()=> Debug.Log("Completed")) ; // 좌클릭할 때 우클릭이 유지된 상태면 OnNext(), // 우클릭이 안된 상태에서 좌클릭만 하면 OnCompleted() leftMouseDown .TakeWhile(_ => Input.GetMouseButton(1)) //.Subscribe(_ => Debug.Log("Click"), ()=> Debug.Log("Completed")) ; leftMouseDown .TakeLast(5) .TakeUntil(rightMouseDown) .Subscribe(_ => Debug.Log("Click"), () => Debug.Log("Completed")) ; leftMouseDown //.Skip(10) .Skip(TimeSpan.FromMilliseconds(1000)) //.Subscribe(_ => Debug.Log("Click"), ()=> Debug.Log("Completed")) ; leftMouseDown .SkipUntil(rightMouseDown) //.Subscribe(a => Debug.Log("Click" + a), ()=> Debug.Log("Completed")) ; }
private void WhenAllExample() { var parallel = Observable.WhenAll( ObservableWWW.Get("http://google.com/"), ObservableWWW.Get("http://bing.com/"), ObservableWWW.Get("http://unity3d.com/") ); parallel.Subscribe(xs => { Debug.Log(xs[0].Substring(0, 100)); // google Debug.Log(xs[1].Substring(0, 100)); // bing Debug.Log(xs[2].Substring(0, 100)); // unity }); }
// 마우스 클릭 유지 관찰 private void ObserveKeepMousePress() { // 시작 트리거 var beginStream = this.UpdateAsObservable() .Where(_ => Input.GetMouseButtonDown(0)); // 종료 트리거 var endStream = this.UpdateAsObservable() .Where(_ => Input.GetMouseButtonUp(0)); // 시작~종료 트리거 사이에서 매 프레임 OnNext() this.UpdateAsObservable() .SkipUntil(beginStream) .TakeUntil(endStream) .RepeatUntilDisable(this) .Subscribe(_ => Debug.Log("Press")); }
private void TestReactiveProperties() { // 값 초기화할 때마다 OnNext(int) _intProperty .Subscribe(x => Debug.Log(x)); // 5의 배수인 값이 초기화될 때마다 값을 10배로 증가시켜 OnNext(int) _intProperty .Where(x => x % 5 == 0) .Select(x => x * 10) .Subscribe(x => Debug.Log(x)); for (int i = 0; i <= 5; i++) { _intProperty.Value = i; } }
private IEnumerator TestRoutine() { Debug.Log("TestRoutine - 1"); yield return(new WaitForSeconds(1.0f)); Debug.Log("TestRoutine - 2"); yield return(Time.frameCount); // 여기부터 yield return(123); yield return(Time.frameCount); // 여기까지 같은 프레임 yield return(null); yield return(Time.frameCount); // 프레임 넘어감 yield return(12.3); // InvalidCastException }
private void TestObservables() { //// Empty : OnCompleted()를 즉시 전달 //Observable.Empty<Unit>() // .Subscribe(x => Debug.Log("Next"), () => Debug.Log("Completed")); //// Return : 한 개의 메시지만 전달 //Observable.Return(2.5f) // .Subscribe(x => Debug.Log("value : " + x)); //// Range(a, b) : a부터 (a + b - 1)까지 b번 OnNext() //// 5부터 14까지 10번 OnNext() //Observable.Range(5, 10) // .Subscribe(x => Debug.Log($"Range : {x}")); //// Interval : 지정한 시간 간격마다 OnNext() //Observable.Interval(TimeSpan.FromSeconds(1)) // .Subscribe(_ => Debug.Log("Interval")); //// Timer : 지정한 시간 이후에 OnNext() //Observable.Timer(TimeSpan.FromSeconds(2)) // .Subscribe(_ => Debug.Log("Timer")); //// EveryUpdate : 매 프레임마다 OnNext() //Observable.EveryUpdate() // .Subscribe(_ => Debug.Log("Every Update")); // Start : 무거운 작업을 병렬로 처리할 때 사용된다. // 멀티스레딩으로 동작한다. Debug.Log($"Frame : {Time.frameCount}"); Observable.Start(() => { Thread.Sleep(TimeSpan.FromMilliseconds(2000)); MainThreadDispatcher.Post(_ => Debug.Log($"Frame : {Time.frameCount}"), new object()); return(Thread.CurrentThread.ManagedThreadId); }) .Subscribe( id => Debug.Log($"Finished : {id}"), err => Debug.Log(err) ); }
private void SubjectTest() { Subject <string> strSubject = new Subject <string>(); var disposable = strSubject .Subscribe(str => Debug.Log("Next : " + str), () => Debug.Log("End1")); strSubject .DelayFrame(10) .Subscribe(str => Debug.Log("Delayed Next : " + str), () => Debug.Log("End2")); strSubject.OnNext("A"); disposable.Dispose(); strSubject.OnNext("B"); strSubject.OnCompleted(); strSubject.OnNext("C"); }
private void CheckDoubleClick() { // 좌클릭 입력을 감지하는 스트림 생성 var dbClickStream = Observable.EveryUpdate() .Where(_ => Input.GetMouseButtonDown(0)); // 스트림의 동작 정의, 종료 가능한 객체 반환 var dbClickStreamDisposable = dbClickStream .Buffer(dbClickStream.Throttle(TimeSpan.FromMilliseconds(250))) .Where(xs => xs.Count >= 2) //.TakeUntilDisable(this) // 게임오브젝트 비활성화 시 스트림 종료 .Subscribe( xs => Debug.Log("DoubleClick Detected! Count:" + xs.Count), // OnNext _ => Debug.Log("DoubleClick Stream - Error Detected"), // OnError () => Debug.Log("DoubleClick Stream - Disposed") // OnCompleted ); // 스트림 종료 //dbClickStreamDisposable.Dispose(); }
private void TestCustomObservables() { CustomObservables.Instance.MouseDoubleClickAsObservable .Subscribe(_ => Debug.Log("D C")); }
private void TestCombinations() { var leftDownStream = this.UpdateAsObservable() .Where(_ => Input.GetMouseButtonDown(0)); var rightDownStream = this.UpdateAsObservable() .Where(_ => Input.GetMouseButtonDown(1)); // 좌클릭 수 누적 스트림 var leftDownCountStream = leftDownStream .Select(_ => 1) .Scan((a, b) => a + b); // 우클릭 수 누적 스트림 var rightDownCountStream = rightDownStream .Select(_ => 1) .Scan((a, b) => a + b); // 좌클릭 : Down -> Up 일회성 스트림 var leftClickStream = this.UpdateAsObservable() .Where(_ => Input.GetMouseButtonDown(0)) .TakeUntil( this.UpdateAsObservable() .Where(_ => Input.GetMouseButtonUp(0)) ); // 우클릭 : Down -> Up 일회성 스트림 var rightClickStream = this.UpdateAsObservable() .Where(_ => Input.GetMouseButtonDown(1)) .TakeUntil( this.UpdateAsObservable() .Where(_ => Input.GetMouseButtonUp(1)) ); // ======================================================================= // Scan : 이전 메시지와 현재 메시지를 합성 leftDownStream .Select(_ => 5) .Scan((a, b) => a + b) //.Subscribe(x => Debug.Log($"Scan : {x}")) ; // Buffer : 지정한 횟수 또는 시간에 도달할 때까지 값을 누적하고 // 도달 시 리스트 형태로 OnNext() //leftMouseDownStream // .Select(_ => Time.frameCount) // .Buffer(TimeSpan.FromSeconds(2)) // .Subscribe(list => // { // foreach (var x in list) // { // Debug.Log(x); // } // }); leftDownCountStream //.Zip //.ZipLatest //.CombineLatest .WithLatestFrom ( rightDownCountStream, (a, b) => $"Left[{a}], Right[{b}]" ) //.Subscribe(x => Debug.Log(x)) ; leftDownCountStream .Amb(rightDownCountStream) //.Subscribe(x => Debug.Log(x)) ; leftDownCountStream .Pairwise() //.Subscribe(pair => Debug.Log($"{pair.Previous}, {pair.Current}")) ; leftDownCountStream .Buffer(2, 3) //.Subscribe(x => Debug.Log($"{x[0]}, {x[1]}")) ; leftDownStream.Merge(rightDownStream) //.Subscribe(_ => Debug.Log("Left or Right Click")) ; leftClickStream.Concat(rightClickStream) //.Subscribe(_ => Debug.Log("Left or Right Click")) ; this.UpdateAsObservable() .Where(_ => Input.GetMouseButtonDown(0)) .Select(a => 1) .Scan((a, b) => a + b) .TimeInterval() .TakeUntil(rightDownStream) .Finally(() => Debug.Log("finally")) //.Subscribe( // _ => Debug.Log($"Left Click [Interval : {_.Interval}], [Value : {_.Value}]"), // () => Debug.Log("LC - Completed") //) ; this.UpdateAsObservable() .Where(_ => Input.GetMouseButtonDown(0)) .Select(a => 1) .Scan((a, b) => a + b) .Timestamp() .TakeUntil(rightDownStream) .Finally(() => Debug.Log("finally")) //.Subscribe( // _ => Debug.Log($"Left Click [Timestamp : {_.Timestamp}], [Value : {_.Value}]"), // () => Debug.Log("LC - Completed") //) ; }
private void TestObserveValueChanged() { // ObserveEveryValueChanged : 클래스 타입에 대해 모두 사용 가능 this.ObserveEveryValueChanged(x => x._intValue) .Subscribe(x => Debug.Log("Value Changed : " + x)); }