🫠
UniRx部分のSubscribeAwaitへの移行
背景
古いコードをみてると、UniRxのロジックからUniTaskへの移行したいなということが多い.
でも各所でObservableが溢れているので、
どんなふうに移行するのがスムーズかなと考えてみた
サンプル
シンプルなボタンイベントを考える
下記のようなコードを実行してみる
public class Sample : MonoBehaviour
{
[SerializeField] private Button button;
private void Start()
{
// パターン1.
button.OnClickAsObservable()
.Subscribe(async _ => await Run())
.AddTo(this);
// パターン2.
button.OnClickAsObservable()
.Subscribe(_ => Run().Forget())
.AddTo(this);
// パターン3.
button.OnClickAsAsyncEnumerable()
.SubscribeAwait(async _ => await Run())
.AddTo(this);
// パターン4.
button.OnClickAsObservable()
.ToUniTaskAsyncEnumerable()
.SubscribeAwait(async _ => await Run())
.AddTo(this);
}
private async UniTask Run()
{
Debug.Log("Before");
await UniTask.Delay(TimeSpan.FromSeconds(5));
Debug.Log("After");
}
}
挙動
5秒間で2回ボタンを連打したときの挙動は下記のようになる
パターン1,2. 即時連続実行される
Before
Before
After
After
パターン3. 一度だけ実行される (実行中の連打は無視)
Before
After
パターン4. 即時実行されずにイベントは逐次実行される
Before
After
Before
After
パターン1は、void asyncのコードになるので、望ましくない.
パターン2は、即時実行されてしまい重複的に処理を行うので好ましくない
パターン3は、UniTaskだけで完結していて、重複処理も防止できており最も好ましい. ただイベントソースから書き直すような対応が必要なので、Observableが各所に散らばっている移行期には利用しづらい
パターン4は、重複処理が防げているが、処理中のイベントをQueuingしてしまっているので、惜しい
移行期には、パターン4にthrottle挟むなり、Rxの独自オペレーター挟むなりで連打防止しつつ、最終的にはパターン3に切り替えるのがいいのかなとおもった。
Discussion