UniRxでThrottle.Subscribe中に値を変更すると、その値が無視されてしまうので気をつけて。という備忘録
確かによく考えるとそうなるかもしれないけれど、微妙に直感的ではなくて引っかかった挙動があったのでメモ。
簡単なコードから話を始めます。
var hoge = new ReactiveProperty<int>(0);
hoge
.Subscribe(x =>
{
Debug.Log($"{Time.frameCount} Subscribe Start hoge = {x}");
hoge.Value = 3;
Debug.Log($"{Time.frameCount} Subscribe End hoge = {x}");
})
.AddTo(this);
await UniTask.DelayFrame(10);
Debug.Log($"{Time.frameCount} Update hoge = 1");
hoge.Value = 1;一瞬こんがらがりますが、実行結果が以下のようになるのは自明でしょう。
1 Subscribe Start hoge = 0
1 Subscribe End hoge = 0
11 Update hoge = 1
11 Subscribe Start hoge = 1
11 Subscribe Start hoge = 3
11 Subscribe End hoge = 3
11 Subscribe End hoge = 1もちろん、最終的にhoge.Valueは3ですし、最後にSubscribeで渡ってくる値も3です。
続いて、DelayFrameを噛ませてみました。
hoge
.DelayFrame(1)
.Subscribe(x =>ちょっとややこしくなってきましたが、まあこうなるのは分かるでしょう。
3 Subscribe Start hoge = 0
3 Subscribe End hoge = 0
5 Subscribe Start hoge = 3
5 Subscribe End hoge = 3
11 Update hoge = 1
12 Subscribe Start hoge = 1
12 Subscribe End hoge = 1
14 Subscribe Start hoge = 3
14 Subscribe End hoge = 3さっきと変わらず、最終的にhoge.Valueは3ですし、最後にSubscribeで渡ってくる値も3です。
ここからが本題、さっきのDelayFrameをThrottleFrameに変えてみました。
hoge
.ThrottleFrame(1)
.Subscribe(x =>この実行結果は
3 Subscribe Start hoge = 0
3 Subscribe End hoge = 0
11 Update hoge = 1
12 Subscribe Start hoge = 1
12 Subscribe End hoge = 1になります。
最終的なhoge.Valueは3になりますが、Subscribeに3が渡ってくることはありません。
気持ちとしては13フレーム目で3が渡ってきて欲しいんですが、確かにOnNext中に値が変わったらThrottleに巻き込まれて握り潰されちゃうのかなーと思った挙動でした。