この記事でのバージョン
Unity 2021.3.4f1
はじめに
UniRxはUpdateAsObservableを使う事で簡単にUpdateをストリーム化する事ができ、
さらにFirstを組み合わせる事で条件が揃った時に1度だけ処理をするという実装が簡単に出来ます。
private bool _flag = false; private void Start() { //_flagがtrueになった時になんか処理する this.UpdateAsObservable() .First(_ => _flag) .Subscribe(_ =>{ /*なんか処理*/ }); }
しかしその条件が揃って処理が行われる前に
シーン遷移やUnityエディタを停止してオブジェクトが破棄されると以下のようなエラーが出ます。
InvalidOperationException: sequence is empty
UniRx.InternalUtil.ExceptionExtensions.Throw
今回はそういう場合の原因と対処法です!
原因と対処法
UpdateAsObservableはGameObjectが破棄された際に自動的にOnCompletedが発行されます。
しかし、Firstは値を発行(OnNext)する前にOnCompletedされると最初のようなエラーが出る仕様です。
なので今回のような状況でもエラーを出したくない時はFirstOrDefaultを使います。
private bool _flag = false; private void Start() { //_flagがtrueになった時になんか処理する this.UpdateAsObservable() .FirstOrDefault(_ => _flag) .Subscribe(_ =>{ /*なんか処理*/ }); }
ただしawaitで待つような処理だとその後の処理が実行されてしまう点には注意が必要です。
private bool _flag = false; private async void Start() { Debug.Log($"待機開始"); //_flagがtureになるまで待つ //※オブジェクトが破棄されると_flagがtrueになってなくも先の処理が実行されてしまう await this.UpdateAsObservable().FirstOrDefault(_ => _flag); Debug.Log($"待機終了"); }
こんな時は自身(this)が破棄されてnullになってないかチェックすると良いかもしれません。
Debug.Log($"待機開始"); //_flagがtureになるまで待つ await this.UpdateAsObservable().FirstOrDefault(_ => _flag); //破棄されている場合はこれ以降の処理しない if (this == null) { return; } Debug.Log($"待機終了");