本日はUniRxの小ネタ枠です。
UniRxでPublishを使ってColdの性質のObservableをHotの性質のObservableに変換してみます。
Hot/Cold
UniRxにおけるHotとColdのObservableの違いについては以下の記事を参照ください。
bluebirdofoz.hatenablog.com
Publishオペレータ
Publishオペレータを使うとColdのObservableをHotのObservableに変換することができます。
ただしPublishを行うだけでは通知は流れてこず、Publishの後にConnectオペレータを利用して初めてColdのObservableから通知が流れる点に注意が必要です。
// ColdのObservable var rangeObservable = Observable.Range(1, 2); // PublishでHotのObservableの性質を持つObservableに変換されるが // この時点でColdのObservableから通知は流れてこない var rangeHotObservable = rangeObservable.Publish(); // Connectを行った時点でColdのObservableから通知が発生する rangeHotObservable.Connect();
サンプルスクリプト
以下のサンプルスクリプトでColdのObservableを直接購読する場合と、PublishオペレータでHotのObservableに変換したものを購読する場合の動作を比較します。
・PublishTest.cs
using UniRx; using UnityEngine; public class PublishTest : MonoBehaviour { [ContextMenu("ColdObservableTest")] public void ColdObservableTest() { // RangeオペレータはColdのObservableになる // Coldのため、この時点では 1, 2, 3 の通知が発行されない var rangeObservable = Observable.Range(1, 2); Debug.Log("Subscribe"); // ColdのObservableは購読ごとに別々のストリームが生成されて購読と同時に通知が発生する rangeObservable.Subscribe(x => Debug.Log($"Subscribe1: {x}")); rangeObservable.Subscribe(x => Debug.Log($"Subscribe2: {x}")); } [ContextMenu("PublishObservableTest")] public void PublishObservableTest() { // RangeオペレータはColdのObservableになる // Coldのため、この時点では 1, 2, 3 の通知が発行されない var rangeObservable = Observable.Range(1, 2); // PublishでHotのObservableを準備する // この時点ではColdのObservableから通知は流れてこない var rangeHotObservable = rangeObservable.Publish(); Debug.Log("Subscribe"); // HotのObservableは全ての購読に対して同一のストリームで通知が発生する rangeHotObservable.Subscribe(x => Debug.Log($"Subscribe1: {x}")); rangeHotObservable.Subscribe(x => Debug.Log($"Subscribe2: {x}")); // Connectを行った時点でColdのObservableから通知が発生する rangeHotObservable.Connect(); } }
ColdのObservableを直接購読する場合
ColdのObservableを直接購読する場合では購読のタイミングで個別のストリームが作成されて全ての通知を受け取ります。
このため、それぞれの購読で 1 ~ 2 の通知を受け取ってログ出力が行われます。
PublishオペレータでHotのObservableに変換したものを購読する場合
HotのObservableに変換した場合、全ての購読が同じストリームを参照して通知を受け取ります。
このため、Connectオペレータ実行後、1 と 2 の通知ごとに購読によるログ出力が行われる形になります。