(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

(:3[kanのメモ帳]


本ブログの運営者kan.kikuchiが個人で開発したゲームです!

    

UniRxのUpdateAsObservable().Firstを使ったらシーン遷移時やエディタ停止時にInvalidOperationException: sequence is emptyというエラーが出る場合の原因と対処法 【Unity】【UniRx】


このエントリーをはてなブックマークに追加



この記事でのバージョン
Unity 2021.3.4f1


はじめに

UniRxUpdateAsObservableを使う事で簡単に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($"待機終了");