Unity (2021.3.2f1} UniRX (7.1.0)
プレイ状態でコンパイル(ホットリロード)すると動かない
例としてUpdateを毎フレーム実行するUpdateAsObservableのコードで解説します。
this.UpdateAsObservable() .Subscribe(_ => { Debug.Log("Update!!!"); }, () => { Debug.Log("Completed!!!"); }); int a = 0; // これを int a = 1とかに変更
上記コードはプレイ実行すると毎フレームがログ出力されるだけのものです。
今回の内容はプレイ中にスクリプトの中身を書き換えた場合の話です。
どうなるかというと、
スクリプトを書き換えてUnity画面がアクティブになると再コンパイルが走ります。
これは別に普通の挙動ですが、コンパイル後にコンソール画面を確認するとログが止まります。
つまりUpdateAsObservableが動かなくなっている現象が発生しましたというものです。
プレイ終了時にOnCompletedが呼ばれない
通常動作だとUpdateAsObservalはプレイ終了時にDisposeを内部で呼び出しているため、SubscribeしていればOnCompletedが呼ばれるようになっています。
しかしプレイモード中の再コンパイルが走るとなぜか呼ばませんでした。
※一応Updateは止まります。
OnCompletedが呼ばれないのはいいのですが、メモリ上に生き残ってしまっていないかが心配です。というのも再コンパイル時に下記警告が発生することがありました。UniRXが要因かは定かではないのですが、状況から見て濃厚です。
The referenced script (Unknown) on this Behaviour is missing!
さらに一度発生すると次から再コンパイルで100%で発生します。。しかもこの警告誰が発行したかが追えないというもはやハメ技です。
解決方法
UniRXを使うのであればホットリロードは使わないようにするのが吉だと思います。
解決方法としてはプレイモード中にスクリプトを書き換えた場合にプレイ終了までコンパイルされないようにするですね。
それができる設定がUnityにあります!
設定手順ですが、
Preferences > General
を開きます
[Script Changes While Playing] を [Recompile After Finished Playing]に変更します。


これでホットリロードはできなくなりますが再コンパイルも走らないので安全にデバッグすることができるようになると思います!
他にも[Stop Playing And Recompile]がありますが、
こちらはプレイを強制終了させてコンパイルするというものです。ただ効率的には微妙だと思います。。
以上となります。
正直根本解決ではないのですがこれがベターな方法だと思いましたので共有させていただきました。