UniRxのシンプルなサンプル その2(WhereとSelect)


UniRxのシンプルなサンプルの取扱説明書
前(Subscribe)
次(FirstとTake)

初めてのフィルターメソッド

IObservableはIEnumerableと対になっているからLINQの構文のWhereとか使えるんだよ!

これを聞いた時僕はこう思いました。

は?

いやだってイベントの話してるのになんでLINQが出てくるのか意味がわからなかったです。

更に
第1回 Reactive Extensionsの概要と利用方法

IObservable<T>/IObserver<T>インターフェイスの成り立ち自体が、IEnumerable<T>/IEnumerator<T>インターフェイスを反転させて作られたものだからだ。

はああああ?

実際はプッシュされてくる値をLINQでいろいろできるというお話でした。

あと反転云々はとりあえず気にしなくていいと思います。
いろいろ使ってからのほうが確実に理解できます。
わからない時に深く考えると僕みたいに挫折します。

そこで今回はWhereとSelectのお話です。

前準備

今回からMoveメソッドという物を持ったBaseクラスというものを定義してそれを継承する形にします。
(Rx部分以外を省略したいため)

Base.cs
using UnityEngine;
public class Base : MonoBehaviour {
    /// <summary>
    /// (dx,dy)だけ移動させる
    /// </summary>
    /// <param name="dx"></param>
    /// <param name="dy"></param>
    public void Move (float dx,float dy) {
        gameObject.transform.position += new Vector3(dx, dy, 0);
    }
}

今回は前回のSubsribeオブジェクトの他にSelect,Whereオブジェクトを作っています。

赤がSubscribeで青がWhereで緑がSelectですね。
それぞれWhereSampleとSelectSampleをくっつけています。

Where

WhereSampleはこんなコードになっています。

WhereSample
using UnityEngine;
using System.Collections;
using UniRx;
using UniRx.Triggers;

public class WhereSample : Base {

    // Use this for initialization
    void Start () {
        //Returnで(0,0.5)という値をSubscribe内に流し込んでる
        Observable.Return(new Vector2(0, 0.5f)).Subscribe(v => gameObject.transform.position = v);

        //Whereで左クリックの間しか値がプッシュされないようにしている
        this.UpdateAsObservable()
            .Where(_ => Input.GetMouseButton(0))
            .Subscribe(l => Move(0.01f, 0));
    }

}

初期位置が変わってるのは置いておいて

UpdateAsObservable()の後にWhere(_ => Input.GetMouseButton(0))が挟まっています。
これはLINQのWhereなのでInput.GetMouseButton(0)がtrueの時しかここを通過できません。
これを通過した値のみSubscribeまで処理が行きます。

結果として左クリックを押している間のみ右に移動する事になります。

Select

一方Selectはプッシュされた値を射影するメソッドです。

SelectSample
using UnityEngine;
using System.Collections;
using UniRx;
using UniRx.Triggers;

public class SelectSample : Base {

    // Use this for initialization
    void Start () {
        //Returnで(0,1)という値をSubscribe内に流し込んでる
        Observable.Return(new Vector2(0, 1.5f)).Subscribe(v => gameObject.transform.position = v);

        //Selectを使って入力を加工してあげる
        this.UpdateAsObservable()
            .Select(_ => 2)
            .Subscribe(l => Move(0.01f * l, 0));
    }
}

今度はUpdateAsObservableの後にSelect(l => 2)を挟んでいます。
これで流し込む値が2に変わりました。(今まではUnit型というあまり意味のない値が入っていました。)
その後のSubscribeはSubscribe(l => Move(0.01f * l, 0));と0.01のl倍移動します。l==2なので0.01移動するSubscribeより2倍早く移動することになります。

実行してみた

というわけで結果こんなかんじになりました。

今回はここまで