【Unity】【UniRx】時間系のオペレータまとめ

UniRxの時間に関連するオペレータをまとめました。

Interval / IntervalFrame

一定間隔に値を流します。
FrameIntervalというメソッドもあるので注意。

Observable.IntervalFrame(30)
    .Do(_ => Debug.Log("On Next"))
    .Subscribe();

Timer / TimerFrame

第一引数だけ遅延させた後、第二引数の間隔で値を流します。
DelayとIntervalを組みわせたようなもの。
第一引数だけ指定すれば遅延後に一回だけ値を流して終わります。

Observable.TimerFrame(30, 100)
    .Do(_ => Debug.Log("On Next"))
    .Subscribe();

Delay / DelayFrame

流れてきた値を数秒 / 数フレーム遅らせて流すオペレータ。

var inputObservable        = Observable
    .EveryUpdate()
    .Where(_ => Input.anyKeyDown)
    .Delay(System.TimeSpan.FromSeconds(3.0f))
    .Do(_ => Debug.Log("Any Key Down"))
    .Subscribe();

DelaySubscription / DelayFrameSubscription

購読開始タイミングを遅らせるオペレータです。

// 3秒後にOn Subscribeが表示され、そこからOnNextが流れてくる
Observable.EveryUpdate()
    .DoOnSubscribe(() => Debug.Log("On Subscribe"))
    .Do(_ => Debug.Log("On Next"))
    .DelaySubscription(System.TimeSpan.FromSeconds(3.0f))
    .Subscribe();

TimeInterval / FrameInterval

前回値が流れたときからの秒数 / frame数を取得できます。

var inputObservable        = Observable.EveryUpdate().Where(_ => Input.anyKeyDown);
Observable.TimeInterval(inputObservable)
    .Do(x => Debug.Log("前回から" + x.Interval + "秒経過"))
    .Subscribe();

Sample / SampleFrame

一定間隔ごとに、値が流れてきていたら流すオペレータ。
いくつ流れてきていても1個だけ流します。

var timerObservable        = Observable.IntervalFrame(1);
Observable.Sample(timerObservable, System.TimeSpan.FromSeconds(1.0f))
    .Do(x => Debug.Log("On Next"))
    .Subscribe();

Throttle / ThrottleFrame

一定時間値が流れてこなかったら、最後に流れてきた値を流すオペレータ。

// 連打してからしばらく話すと一個だけ流れる
var anyKeyObservable        = Observable
    .EveryUpdate()
    .Where(_ => Input.anyKeyDown);
Observable.Throttle(anyKeyObservable, System.TimeSpan.FromSeconds(1.0f))
    .Do(x => Debug.Log(x))
    .Subscribe();

ThrottleFirst / ThrottleFirstFrame

値が流れてきたら一個だけ流して、そのあと一定時間は流さずに、一定時間経過後にまた流すオペレータ

var intervalObservable     = Observable.IntervalFrame(1);
Observable.ThrottleFirst(intervalObservable, System.TimeSpan.FromSeconds(1.0f))
    .Do(x => Debug.Log(x))
    .Subscribe();

BatchFrame

処理を数フレーム分まとめて流すオペレータです。

// BatchFrameにより同じフレームにAとBが同時押しされても一回しか流れない
var inputAObservable        = Observable.EveryUpdate().Where(_ => Input.GetKeyDown(KeyCode.A));
var inputBObservable        = Observable.EveryUpdate().Where(_ => Input.GetKeyDown(KeyCode.B));
Observable.Merge(inputAObservable, inputBObservable)
    .BatchFrame(0, FrameCountType.Update)
    .Do(_ => Debug.Log("A or B Key Down"))
    .Subscribe();

NextFrame

1フレーム遅らせるときに使います。

Observable.NextFrame()
    .Do(_ => Debug.Log("Next Frame"))
    .Subscribe();

Timeout / TimeoutFrame

一定時間値が流れてこなかったらエラーにしたい場合に使うオペレータです。

// 5秒以内に何かキーを押さないとTimeoutException
var anyKeyObservable        = Observable
    .EveryUpdate()
    .Where(_ => Input.anyKeyDown);
Observable.Timeout(anyKeyObservable, System.TimeSpan.FromSeconds(5.0f))
    .Do(x => Debug.Log(x))
    .DoOnError(_ => Debug.Log("Error"))
    .Subscribe();