【UniRx】Observable自体を変換するオペレータ #96
前回の成果
Obsevableを合成するオペレータについて学んだ。
今回やること
今回はObservable自体の変換をまとめます。
- 前回の成果
- 今回やること
- ObservableをReadOnlyReactivePropertyに変換
- Selectで別のReactivePropertyに変換
- CombineLatestで2つのReactivePropertyを比較
- Observableをコルーチンに変換
- 参考サイト様
ObservableをReadOnlyReactivePropertyに変換
ToReadOnlyReactiveProperty
ReadOnlyReactivePropertyとは、名前のままReactivePropertyの読み取り専用のものになります。
ReactivePropertyとは、値を渡した際に、同じ値の場合何もしない、違う値の場合OnNextを発行してくれるものとなります。
詳しくは以下で解説しています。
ToReactivePropertyとToReadOnlyReactivePropertyがあります。
こちらはどちらも戻り値に、ReadOnlyReactiveProperty<T>を返しているので、中身的には同じものとなります。
ToReactivePropertyの定義
public static IReadOnlyReactiveProperty<T> ToReactiveProperty<T>(this IObservable<T> source) { return new ReadOnlyReactiveProperty<T>(source); }
ToReadOnlyReactivePropertyの定義
public static ReadOnlyReactiveProperty<T> ToReadOnlyReactiveProperty<T>(this IObservable<T> source) { return new ReadOnlyReactiveProperty<T>(source); }
1秒に1回、現在時刻を通知する
Intervalを使用することにより、指定した間隔でメッセージを発行することができます。
その発行をDateTime.Nowにすることにより1秒に1回、現在時刻を通知することができます。
サンプルコード
/// <summary> /// 1秒に1回、現在時刻を通知する /// </summary> private void ToReadOnlyReactivePropertyTimer() { ReadOnlyReactiveProperty<string> timer = Observable .Interval(TimeSpan.FromSeconds(1)) .Select(_ => DateTime.Now.ToString()) .ToReadOnlyReactiveProperty(); timer .Subscribe(x => { Debug.Log("Now Time : " + x); }, () => { Debug.Log("Timer onCompleted"); }).AddTo(this); }
結果
Selectで別のReactivePropertyに変換
Selectを使用することにより、今回はint型のReactivePropertyをbool型に変換することができます。
こうすることにより、HPの比較といったこともできるようになります。
サンプルコード
/// <summary> /// Selectで別のReactivePropertyに変換 /// </summary> private void ToReadOnlyReactivePropertySelect() { const int ENERGY_HP = 50; ReactiveProperty<int> hp = new ReactiveProperty<int>(1); // SelectでintをboolのReactivePropertyへ変換 // HPが50を超えていたら元気 ReadOnlyReactiveProperty<bool> isEnergy = hp.Select(x => x >= ENERGY_HP) .ToReadOnlyReactiveProperty(); // isEnergy = false Debug.Log(string.Format("hp : {0}, isEnergy : {1}", hp, isEnergy)); hp.Value = ENERGY_HP; // isEnergy = true Debug.Log(string.Format("hp : {0}, isEnergy : {1}", hp, isEnergy)); }
結果
CombineLatestで2つのReactivePropertyを比較
CombineLatestは、合成元のObservableに値が流れたら、他のObservableの最後に発行した値を流すオペレータです。
今回の場合ですと、value1かvalue2の値が変化する度に値が比較されます。
/// <summary> /// CombineLatestで2つのReactivePropertyを比較 /// </summary> private void ToReadOnlyReactivePropertyCombineLatest() { ReactiveProperty<int> value1 = new ReactiveProperty<int>(0); ReactiveProperty<int> value2 = new ReactiveProperty<int>(1); // value1とvalue2を比較して同じ値だったらtrue ReadOnlyReactiveProperty<bool> isSameValue = Observable .CombineLatest(value1, value2, (x, y) => x == y) .ToReadOnlyReactiveProperty(); Debug.Log(string.Format("value1 : {0}, value2 : {1}, isSameValue : {2}", value1, value2, isSameValue)); value1.Value = 5; Debug.Log(string.Format("value1 : {0}, value2 : {1}, isSameValue : {2}", value1, value2, isSameValue)); value2.Value = 5; Debug.Log(string.Format("value1 : {0}, value2 : {1}, isSameValue : {2}", value1, value2, isSameValue)); }
結果
Observableをコルーチンに変換
ToYieldInstruction
/// <summary> /// タイマーコルーチンの実行 /// </summary> private void ExcuteTimerCoroutine() { Observable .FromCoroutine(TimerCoroutine) .Subscribe(x => { Debug.Log("OnNext"); }, () => { Debug.Log("OnCompleted"); }); } /// <summary> /// タイマーコルーチン /// </summary> /// <returns></returns> private IEnumerator TimerCoroutine() { Debug.Log("1秒後に終了します"); yield return Observable .Timer(TimeSpan.FromSeconds(1)) .ToYieldInstruction(); }
結果
また、SelectManyやWhenAllといったオペレータを使用することにより複数のObservableから変換したコルーチンを扱うこともできます。
詳しくは、以下で紹介しています。
今回は以上となります。
ここまでご視聴ありがとうございました。