SubscribeOnMainThread
1. 概要
SubscribeOnMainThread は、ソース Observable への実際の購読処理を Unity のメインスレッドで実行する R3.Unity のオペレーターです。内部的には SubscribeOn(UnityFrameProvider.Update) と同義です。
購読時に Unity API を触る Observable、または GameObject / Component の状態を購読開始時に読む Observable では、購読処理を Unity メインスレッドへ寄せたい場合があります。
2. シグネチャ
public static Observable<T> SubscribeOnMainThread<T>(
this Observable<T> source)3. マーブルダイアグラム
値自体は変更されません。ソースへの購読開始が Unity のメインスレッド(Update)で行われます。
4. サンプルコード
Observable
.Create<Unit>(observer =>
{
// Unity API に触れる購読初期化をメインスレッドで実行したい
transform.position = Vector3.zero;
observer.OnNext(Unit.Default);
observer.OnCompleted();
return Disposable.Empty;
})
.SubscribeOnMainThread()
.Subscribe()
.AddTo(this);5. 補足
ObserveOnMainThread との違い
SubscribeOnMainThread が制御するのは購読処理の実行場所です。OnNext などの通知を Unity メインスレッドで受け取りたい場合は ObserveOnMainThread を併用してください。
| 観点 | SubscribeOnMainThread | ObserveOnMainThread |
|---|---|---|
| 変更するもの | ソースへの Subscribe と Dispose の実行場所 | OnNext / OnErrorResume / OnCompleted の実行場所 |
| 主な用途 | 購読開始時に Unity API を触る処理を Unity メインスレッドで開始する | GameObject / Component / UI の更新を Unity メインスレッドで行う |
Subscribe(...) 内のラムダに効くか | 直接は効かない | 効く |
| Unity オブジェクト更新に必要か | これだけでは不十分 | 多くの場合こちら |
SubscribeOnMainThread は、名前から「Subscribe(x => ...) の中身を Unity メインスレッドで実行する」と誤解されやすいですが、そうではありません。SubscribeOnMainThread が動かすのは、ソース Observable に対する購読開始処理です。OnNext を受け取る場所や、Subscribe に渡したラムダの実行場所を変えたい場合は ObserveOnMainThread を使います。
// 誤解しやすい例: transform 更新がメインスレッドで行われる保証にはならない
observable
.SubscribeOnMainThread()
.Subscribe(x => transform.position = x)
.AddTo(this);Unity オブジェクトや UI を更新したい場合は、通知を Unity メインスレッドへ戻します。
observable
.ObserveOnMainThread()
.Subscribe(x => transform.position = x)
.AddTo(this);SubscribeOnMainThread が有効なのは、購読時点で Unity API に触る Observable です。たとえば購読開始時に GameObject の状態を読む、Unity イベントへ登録する、Component の初期化を行う、といった処理を Unity メインスレッドで開始したい場合に使います。
Observable.Create<Vector3>(observer =>
{
// この購読初期化を Unity メインスレッドで実行したい
observer.OnNext(transform.position);
observer.OnCompleted();
return Disposable.Empty;
})
.SubscribeOnMainThread()
.ObserveOnMainThread()
.Subscribe(position => positionText.text = position.ToString())
.AddTo(this);SubscribeOnMainThread は通常、チェーン内の位置より「ソースへの購読開始」に効きます。一方で、ObserveOnMainThread は置いた位置より下流の通知処理に効きます。Unity オブジェクトを更新したいだけなら、まず ObserveOnMainThread を使う、と覚えると混同しにくくなります。