UniRx: SubscribeWithState は Subscribe より効率がよい

以下のサンプルは、1 秒ごとにテキストを更新するサンプルです。

using System;
using UniRx;
using UnityEngine;
using UnityEngine.UI;

public class Main : MonoBehaviour
{
    [SerializeField] private Text _text = null;

    void Start()
    {
        Observable.Interval(TimeSpan.FromSeconds(1f))
            .Select(e => "Count " + e)
            .Subscribe(e => _text.text = e)
            .AddTo(this);
    }
}

Subscribe のところに注目してください。

.Subscribe(e => _text.text = e);

引数にクロージャを渡しています。このクロージャの生成コストを抑える手段があり、それはSubscribe の代わりに SubscribeWithState を使うことです。

void Start()
{
    Observable.Interval(TimeSpan.FromSeconds(1f))
        .Select(e => "Count " + e)
        // 外部変数を参照しないようになった(クロージャを排除できた)
        .SubscribeWithState(_text, (e, text) => text.text = e)
        .AddTo(this);
}

UniRx ではこのパターンは SubscribeToText というメソッドで定義されています。

public static partial class UnityUIComponentExtensions
{
    public static IDisposable SubscribeToText(this IObservable<string> source, Text text)
    {
        return source.SubscribeWithState(text, (x, t) => t.text = x);
    }
}

ですので、下のように書くことができます。

void Start()
{
    Observable.Interval(TimeSpan.FromSeconds(1f))
        .Select(e => "Count " + e)
        .SubscribeToText(_text)            
        .AddTo(this);
}

参考