LoginSignup
3
6

More than 5 years have passed since last update.

UniRxで複数のボタンが指定の順番で押されたかを判定する

Last updated at Posted at 2017-12-10

解きたい問題

  • ボタンが 3 つあるとします(それぞれ 1, 2, 3 番とする)
  • ボタンが特定の順番で押されたときに限り、指定の処理を行いたい(よくあるパズル)

UniRx を使うと、外部に変数を定義することなく、オペレータの組み合わせのみで実現することができます。

プログラム

以下は、ボタンが 1, 3, 2 の順番で押されたかどうかを判定するプログラムです。

var o = Observable.Merge(
    _button1.OnClickAsObservable().Select(_ => _button1),
    _button2.OnClickAsObservable().Select(_ => _button2),
    _button3.OnClickAsObservable().Select(_ => _button3));

o.Buffer(3, 1)
    .Where(e => e[0] == _button1 && e[1] == _button3 && e[2] == _button2)
    .First()
    .Subscribe(e => Debug.Log("1, 3, 2 の順にボタンが押されました"));
  • Merge で 3 つのボタンクリックイベントをマージ
  • Buffer でボタンのクリックイベントを 3 つずつにまとめる
  • Where で押された順番が 1, 3, 2 かどうかフィルタリング
  • First で条件を満たした先頭要素のみ取り出す

正しいボタンが押されたときに何らかの処理を行いたい

  • 押されたボタンが正しい手順と一致する場合は、そのボタンの色を変える
  • 誤ったボタンが押された場合は、全てのボタンの色をリセットする(最初からやり直し)

プログラムは以下になります。

var o = Observable.Merge(
    _button1.OnClickAsObservable().Select(_ => _button1),
    _button2.OnClickAsObservable().Select(_ => _button2),
    _button3.OnClickAsObservable().Select(_ => _button3));

o.Scan(0, (step, button) =>
{
    switch (step)
    {
        case 0: // はじめに _button1 を押したか
            if (button == _button1)
            {
                _button1.GetComponent<Image>().color = Color.gray;
                return 1; // 次のステップへ
            }
            break;

        case 1: // つぎに _button3 を押したか
            if (button == _button3)
            {
                _button3.GetComponent<Image>().color = Color.gray;
                return 2; // 次のステップへ
            }
            break;

        case 2: // さいごに _button2 を押したか
            if (button == _button2)
            {
                _button2.GetComponent<Image>().color = Color.gray;
                return 3; // Where でフィルタリングする値
            }
            break;
    }

    // 誤ったボタンが押されたときは、ボタンの色を初期値に戻す
    foreach (var b in new[] { _button1, _button2, _button3 })
        b.GetComponent<Image>().color = Color.white;

    return 0; // 最初のステップにもどる
}).Where(e => e == 3).First().Subscribe(e => Debug.Log("1, 3, 2 の順番にボタンが押されました"));
  • Merge で 3 つのボタンのクリックイベントをマージ
  • Scan でボタンの押された順番をチェック。進行状況を step で引き回す
  • Where で条件を満たすものだけフィルタリング
  • First で先頭要素のみ取り出す

Scan を使えば、今回の問題に限らず、イベントが特定の順番で発生したかを、内部処理だけで完結するように書けますね。

3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6