UniRxについての記事のまとめはこちら
#SubscribeとDispose
RxではObservableを購読してメッセージの待受けを行うことをSubscribeと呼び、その購読を中止することをDisposeと呼びます。
このSubscribeは気をつける点があり、Observableが破棄されたタイミングでちゃんとDisposeする必要があります。
Observableが破棄される際にOnCompletedが発行されれば自動的にDisposeされるのですが、ストリームによってはOnCompletedが発行されない場合もあります。
#Observableの寿命を考慮せずに使った場合
まずは以下のコードとその実行結果を見てください。
using UnityEngine;
using UniRx;
using System;
public class ObservableLifeTime : ObservableMonoBehaviour
{
public override void Start()
{
base.Start();
//1秒ごとにメッセージを発信するObservable
Observable.Timer(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1))
.Subscribe(x => Debug.Log(x));
//3秒後にGameObjectを削除する
Invoke("DestroyGameObject", 3);
}
/// <summary>
/// ログを吐いて削除する
/// </summary>
private void DestroyGameObject()
{
Debug.Log("Destroy");
Destroy(this.gameObject);
}
}
実行結果
DestroyでGameObjectが破棄されたにも関わらず、Observable.Timerで作ったストリームが稼働し続けてしまっています。
これはObservable.Timerで作ったObservableがstaticとして生成されてしまい、GameObjectとは関係なく独立して動作してしまっているためです。
#AddToでSubscribeとGameObjectを紐付ける
AddToメソッドを使うとこの問題を簡単に解決することができます。
using UnityEngine;
using UniRx;
using System;
public class ObservableLifeTime : ObservableMonoBehaviour
{
public override void Start()
{
base.Start();
//1秒ごとにメッセージを発信するObservable
Observable.Timer(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1))
.Subscribe(x => Debug.Log(x))
.AddTo(this.gameObject); //指定GameObjectの寿命に紐付ける
//3秒後にGameObjectを削除する
Invoke("DestroyGameObject", 3);
}
/// <summary>
/// ログを吐いて削除する
/// </summary>
private void DestroyGameObject()
{
Debug.Log("Destroy");
Destroy(this.gameObject);
}
}
AddToを使うことで、SubscribeのDisposeを指定したGameObjectの寿命に紐付け、GameObjectのDestroy時に勝手にDisposeしてくれるようになりました。
これでDisposeの管理を気にせずにファクトリメソッドが使えるようになりました!
ただし、OnCompletedが飛ぶ訳ではないのでその点は気をつけましょう。