【OnClickAsObservable】UniRxでボタンのクリック回数をテキストに表示する【SubscribeToText】

  • 9
    Like
  • 0
    Comment
More than 1 year has passed since last update.

はじめに

 この投稿では、ボタンのクリック回数をテキストに表示する処理をUniRxを使って実装します。またそれを通じて、UniRxがUIイベント用に提供しているいくつかのメソッドを紹介します。

UniRxって?

 UniRxはneueccさんが、UnityでもReactiveExtensionsを使えるように移植したものです。またReactiveExtensionsと比べて、UnityのライフサイクルメソッドやUIイベント用機能拡張もされているます。Asset Storeからでもgithubからでも入手できます。

 詳しくは、neueccさんの「Reactive Programming by UniRx for Asynchronous & Event Processing」やtoRisouPさんの「未来のプログラミング技術をUnityで -UniRx-」をご覧ください。

UniRxを使ってボタンのクリック回数を数えてみる(もっとよくなるよ)

 それでは、UniRxを使ってボタンのクリック回数を数えてみます。

using UnityEngine;
using UnityEngine.UI;
using UniRx;

//  この節のコードはもっと簡潔に書くことができます。
public class ButtonClickCount : MonoBehaviour
{
    [SerializeField] Button button;
    [SerializeField] Text text;

    void Awake ()
    {
        button.onClick.AsObservable ()
            .Select (_ => 1)
            .Scan (0, (element, acc) => element + acc)
            .Subscribe (count => text.text = count.ToString ())
            .AddTo(gameObject);
    }
}

 コメントも書きましたが、このコードはさらに簡潔にすることができます。ですが、ひとまずこのコードを見てきます。まずは次のコード片から。

button.onClick.AsObservable ()

 button.onClickは、Buttonクラスのプロパティです。onClickのクラスはButtonClickedEventです。ところでこのButtonClickedEventクラスには、AsObservableという名前のメソッドはありません。

 これはUniRxで拡張された機能・メソッドです。

 UniRxのUnityEventExtensionsというクラスは、UnityEventやUnityEvent<T>の拡張メソッドとしてAsObservableメソッドを提供しています。ButtonClickedEventクラスは、UnityEventのサブクラスなので、AsObservableというメソッドを呼べるようになりました。このAsObservableメソッドを用いることで、クリックなどUnityEventの発火をIObservable<Unit>で扱うことが可能になります。これによりRxのメソッドを使って処理を簡潔に記述することが可能です。

 のふたつについては、「【Unityでも】UniRxを使ってみた。マウスクリックの回数を数える【リアクティブプログラミング】」という記事ですこし紹介しているのでみてください。

 AsObservableメソッドでクリックのストレームを生成し、それをSelectで1のストリームに変換、Scanで数値を累積させクリック回数のストリームを生成し、SubscribeメソッドでTextに数値を表示しています。

UniRxを使ってボタンのクリック回数を数えてみる(簡潔になった!)

 UniRxには便利なメソッドが準備されていて、それを使うことでUIイベントを扱うコードをより簡潔に記述することが可能になります。まずは結果のコードを示します。

using UnityEngine;
using UnityEngine.UI;
using UniRx;

public class ButtonClickCount : MonoBehaviour
{
    [SerializeField]
    Button button;
    [SerializeField]
    Text text;

    void Awake()
    {
        button.OnClickAsObservable()
            .Select(_ => 1)
            .Scan(0, (element, acc) => element + acc)
            .SubscribeToText(text)
            .AddTo(gameObject);
    }
}

 変わったのは2点

  • button.OnClickAsObservable ()
  • SubscribeToText (text)

 です。これらは2つのメソッドはUnityUIComponentExtensionsクラスで定義された拡張メソッドです。

Button.OnClickAsObservableメソッド

 UnityUIComponentExtensionsクラス内で、Buttonクラスの拡張メソッドとして、OnClickAsObservableが定義されています。実装を見てみるとbutton.onClick.AsObservable()を内部で呼び出しています。

 UnityUIComponentExtensionsクラスではButtonクラス以外にも、SliderやToggle、ScrollRectに対して、IObservable<T>を生成するメソッドを拡張しています。ところでそれらに対してはButtonと異なり単純ではなく、現時点の値を初期値として流す処理を加えているので注意が必要です。

IObservable<T>.SubscribeToTextメソッド

 UnityUIComponentExtensionsクラス内で、IObservable<T>クラスの拡張メソッドとして、SubscribeToTextが定義されています。このメソッドはText型を引数にとります。IObservable<T>のストリームの要素が来るたびに、T型の要素をToStringした結果を引数としてとったTextに表示します。多分実装を見た方が早いです。(ここ)

 このほかにも、Text型とFunc<T, string>を引数にとるオーバーロードもあります。

まとめ

 ボタンのクリック回数をテキストに表示する処理をUniRxを使って実装しました。またそれを通じて、UniRxがUIイベント用に提供しているいくつかのメソッドを紹介しました。それらを使うことでUIイベントの処理を簡潔に記述することが可能です。

 RxはRxJava、ReactiveExtensionsの記事を使って勉強することが可能ですが、これらの記事にはUniRxの特別のメソッドなどはもちろん記載されていません。Unity固有・UniRx固有のメソッドがあり、それを使うことで簡潔にできるということを理解しておくと便利だなと思いました。