UniRxのシンプルなサンプル その3(FirstとTake)


UniRxのシンプルなサンプルの取扱説明書
前(WhereとSelect)
次(SkipとSkipWhile)

最初の方だけ実行するメソッド

だんだんRxの便利な機能になっていきます。
今回はIEnumerableのLINQではあまり使う頻度の高くないFirstとかTakeです。
(特にTakeって使うことあるんだろうか…?)

一転してRxではとても便利なメソッドになります。
これらは最初の一回だけ実行したいとか最初の数回だけ実行したいとか、そういうことをしたいときに大活躍します。

例えば最初の一回だけしか反応してほしくない送信ボタン
例えばHPが0になったら当たり処理をしてほしくないオブジェクト
とかで使えそうです。

前準備

例によって例のごとくTakeWhileとTakeとFirstを作ってそれぞれのSampleスクリプト貼っつけてます。

First

Firstは100Frame後に1回だけ1.5f右に移動するオブジェクトにしてみます。
コードはこちら

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

public class First : Base
{

    // Use this for initialization
    void Start()
    {
        gameObject.transform.position = new Vector2(0, 1f);

        //クリックされたら右に1.5動かす(但し1回だけ)
        this.UpdateAsObservable()
            .First(l => Input.GetMouseButton(0))
            .Subscribe(l => Move(1.5f, 0));
    }
}

今回から初期位置は直接代入します。

First(Func predicate)を使うと指定したpredicateに合致した値を最初の1回だけその先にプッシュします。
なのでInput.GetMouseButton(0)がtrueになった後にこのオブジェクトは1回だけ1.5f移動します。
(Firstには引数を取らないオーバーロードもあってWhereと組み合わせたりイベントの最初の一回というのを実現したりできます。)

Take

次に最初の数回だけ処理をしたいという要望に答えてくれるTakeです。

こちらは100Frameの間だけ0.01f移動するようにします。

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

public class TakeSample : Base {

    // Use this for initialization
    void Start () {
        gameObject.transform.position = new Vector2(0, 0.5f);

        //Takeで最初の100回以外はカット
        this.UpdateAsObservable()
            .Take(100)
            .Subscribe(l => Move(0.01f, 0));
    }

}


Take(int n)はプッシュされてきた最初のn回だけプッシュしてくれます。
実際は次のTakeWhileとか紹介はしないけどTakeUnitilとかのほうがいっぱい使いそうです。

TakeWhile

TakeWhileは指定した条件が真である間値をプッシュし続けてくれる便利なメソッドです。
今回はxが2を超えるまで右に移動するGameObjectを作ります。

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

public class TakeWhile : Base
{
    // Use this for initialization
    void Start()
    {
        gameObject.transform.position = new Vector2(0, 1.5f);

        //Takeでxが2を超えたらそれ以降はカット
        this.UpdateAsObservable()
            .TakeWhile(l => gameObject.transform.position.x <= 2)
            .Subscribe(l => Move(0.01f, 0));
    }

}

TakeWhile(Func predicate)はpredicateが合致するまで流れてきた値をプッシュし続けます。
なので上記はのコードはl => gameObject.transform.position.x <= 2を満たすまではSubscribeに行きますが、それ以降はSubscribeに値が伝わらないので結果としてx==2くらいで動きが停止することになります。

実行結果

というわけでそれぞれのオブジェクトの停止した場所はこんなかんじになります。

今回はここまで