【UniRx】ファクトリメソッドオペレータ #93
前回の成果
UniTaskのキャンセルについて学んだ。
今回やること
UniRxで何かしたいときに、どのオペレータを呼べばよいのか混乱したので、具体例も合わせてまとめます。
- 前回の成果
- 今回やること
- ファクトリメソッド
- 値を繰り返し発行
- 指定した範囲で数値を発行
- ObservableをSubscribe時まで遅延
- 一定時間後に値を発行
- 指定フレーム後に値を発行
- 一定間隔で値を発行
- 一定フレーム間隔で値を発行
- 値を発行するストリームの生成
- onErrorを発行する
- OnCompletedを発行する
- 何もしないObservableを定義
- EventをObservableに変換する
- UpdateをObservableに変換する
- FixedUpdateをObservableに変換する
- 参考サイト様
ファクトリメソッド
UniRxが用意してくれているストリームソースメソッド群になります。
値を1つだけ発行
Observable.Return
/// <summary> /// 値を1つだけ発行 /// </summary> private void ExcuteReturn() { // 発行する値 int value = 1; Observable .Return(value) .Subscribe(x => Debug.Log("Return : " + x)); }
結果
値を繰り返し発行
Observable.Repeat
/// <summary> /// 値を繰り返し発行 /// </summary> private void ExcuteRepeat() { // 発行する値 int value = 1; // 繰り返す数 int repeat = 3; Observable .Repeat(value, repeat) .Subscribe(x => Debug.Log("Repeat : " + x)); }
結果
指定した範囲で数値を発行
Observable.Range
/// <summary> /// 指定した範囲で数値を発行 /// </summary> private void ExcuteRange() { // 開始する値 int start = 5; // 繰り返す数 int count = 3; Observable .Range(start, count) .Subscribe(x => Debug.Log("Range : " + x)); }
結果
ObservableをSubscribe時まで遅延
Observable.Defer
/// <summary> /// ObservableをSubscribe時まで遅延 /// </summary> private void ExcuteDefer() { // 遅延させるObservable IObservable<DateTime> deferObservable = Observable.Return(DateTime.Now); Observable.Defer(() => deferObservable ).Subscribe(x => { Debug.Log("Defer : " + x); }); }
結果
一定時間後に値を発行
Observable.Timer
/// <summary> /// 一定時間後に値を発行 /// </summary> private void ExcuteTimer() { int seconds = 1; Observable .Timer(TimeSpan.FromSeconds(seconds)) .Subscribe(x => { Debug.Log("Timer : " + x); }); }
結果
指定フレーム後に値を発行
Observable.TimerFrame
/// <summary> /// 指定フレーム後に値を発行 /// </summary> private void ExcuteTimerFrame() { int frame = 30; Observable .TimerFrame(frame) .Subscribe(x => { Debug.Log("TimerFrame : " + x); }); }
結果
一定間隔で値を発行
Observable.Timer, Observable.Interval
/// <summary> /// 一定間隔で値を発行 /// </summary> private void ExcuteTimerInterval() { // 開始までの時間 int dueTime = 2; // 間隔 int span = 1; // TimerとIntervalとの違いは、開始までの時間を指定できるかどうか Observable .Timer(TimeSpan.FromSeconds(dueTime), TimeSpan.FromSeconds(span)) .Subscribe(x => { Debug.Log("Timer : " + x); }); Observable .Interval(TimeSpan.FromSeconds(span)) .Subscribe(x => { Debug.Log("Interval : " + x); }); }
結果
一定フレーム間隔で値を発行
Observable.TimerFrame, Observable.IntervalFrame
/// <summary> /// 一定フレーム間隔で値を発行 /// </summary> private void ExcuteFrameTimerInterval() { // 開始までの時間 int dueTime = 120; // 間隔 int span = 60; // TimerとIntervalとの違いは、開始までの時間を指定できるかどうか Observable .TimerFrame(dueTime, span) .Subscribe(x => { Debug.Log("TimerFrame : " + x); }); Observable .IntervalFrame(span) .Subscribe(x => { Debug.Log("IntervalFrame : " + x); }); }
結果
値を発行するストリームの生成
Observable.Create
/// <summary> /// 値を発行するストリームの生成 /// </summary> private void ExcuteCreate() { Observable .Create<int>(observer => { int value = 1; observer.OnNext(value); observer.OnCompleted(); return Disposable .Create(() => { Debug.Log("Dispose"); }); }).Subscribe(x => { Debug.Log("Create : " + x); }); }
結果
onErrorを発行する
Observable.Throw
/// <summary> /// onErrorを発行する /// </summary> private void ExcuteThrow() { string message = "error"; Observable .Throw<Unit>(new System.Exception(message)) .Subscribe(_ => { // 呼ばれない Debug.Log("Throw onNext"); }, err => { // 呼ばれる Debug.Log("Throw onError : " + err); }, () => { // 呼ばれない Debug.Log("Throw OnCompleted"); }); }
結果
OnCompletedを発行する
Observable.Empty
/// <summary> /// OnCompletedを発行する /// </summary> private void ExcuteEmpty() { Observable .Empty<Unit>() .Subscribe(_ => { // 呼ばれない Debug.Log("Empty OnNext"); }, err => { // 呼ばれない Debug.Log("Empty onError : " + err); }, () => { // 呼ばれる Debug.Log("Empty OnCompleted"); }); }
結果
何もしないObservableを定義
Observable.Never
/// <summary> /// 何もしないObservableを定義 /// </summary> private void ExcuteNever() { Observable .Never<Unit>() .Subscribe(_ => { // 呼ばれない Debug.Log("Never OnNext"); }, err => { // 呼ばれない Debug.Log("Never OnError : " + err); }, () => { // 呼ばれない Debug.Log("Never OnCompleted"); }); }
結果
EventをObservableに変換する
引数の数によって、使用方法が異なるので注意してください。
Observable.FromEventの引数1つまで
/// <summary> /// EventをObservableに変換する /// 引数1つまではこれで対応可能 /// </summary> private void ExcuteFromEventSimple() { Action<int> fromEventAction = (intValue) => { Debug.Log("Called FromEventAction. int : " + intValue); }; Observable .FromEvent<int>( handler => fromEventAction += handler, handler => fromEventAction -= handler ) .Subscribe(x => { Debug.Log("FromEventSimple onNext. int : " + x); }); fromEventAction(1); }
結果
Observable.FromEventの引数2つ以上, Tuple使用
/// <summary> /// EventをObservableに変換する /// Tupleバージョン /// </summary> private void ExcuteFromEventTuple() { Action<int, string> fromEventAction = (intValue, strValue) => { Debug.Log(string.Format("Called FromEventAction. int : {0}, string : {1}", intValue, strValue)); }; Observable .FromEvent<Action<int, string>, Tuple<int, string>>( handler => (x, y) => handler(Tuple.Create(x, y)), handler => fromEventAction += handler, handler => fromEventAction -= handler ) .Subscribe(x => { Debug.Log(string.Format("FromEventTuple onNext. int : {0}, string : {1}", x.Item1, x.Item2)); }); fromEventAction(1, "message"); }
結果
Observable.FromEventの引数2つ以上, EventArgs使用
/// <summary> /// EventをObservableに変換する /// EventArgsバージョン /// </summary> private void ExcuteFromEventEventArgs() { Action<int, string> fromEventAction = (intValue, strValue) => { Debug.Log(string.Format("Called FromEventAction. int : {0}, string : {1}", intValue, strValue)); }; Observable .FromEvent<Action<int, string>, FromEventActionClass>( handler => (x, y) => handler(new FromEventActionClass() { intValue = x, strValue = y }), handler => fromEventAction += handler, handler => fromEventAction -= handler ) .Subscribe(x => { Debug.Log(string.Format("FromEventEventArgs onNext. int : {0}, string : {1}", x.intValue, x.strValue)); }); fromEventAction(1, "message"); } // ExcuteFromEventEventArgsのClass public class FromEventActionClass : EventArgs { public int intValue; public string strValue; }
結果
UpdateをObservableに変換する
OnCompletedが自動で発行されないので、寿命の管理に注意してください。
また、UpdateAsObservableの方が良い場面の方もあるので使い分けてください。
Observable.EveryUpdate
/// <summary> /// UpdateをObservableに変換する /// </summary> private void ExcuteEveryUpdate() { Observable .EveryUpdate() .Subscribe(x => { Debug.Log("EveryUpdate : " + x); }); }
結果
FixedUpdateをObservableに変換する
OnCompletedが自動で発行されないので、寿命の管理に注意してください。
また、FixedUpdateAsObservableの方が良い場面の方もあるので使い分けてください。
Observable.EveryFixedUpdate
/// <summary> /// FixedUpdateをObservableに変換する /// </summary> private void ExcuteEveryFixedUpdate() { Observable .EveryFixedUpdate() .Subscribe(x => { Debug.Log("EveryFixedUpdate : " + x); }); }
結果
今回は以上となります。
ここまでご視聴ありがとうございました。