UniRxクックブックてきな
今までに書いてきたよくあるRxのパターンを書いてく
class HogeController : Monobehaviour{
[SerializeField]
Button btn;
void do(){
Debug.Log("てすてすてす");
}
void Awake(){
btn.OnClick.AsObservable()
.ThrottleFirst(TimeSpan.FromSeconds(1))
.Subscribe(_ => do()).AddTo(this);
}
}
class RootHoge: MonoBehaviour{
[SerializeField]
ChildHoge[] childrenComponent;
void Awake(){
childrenComponent.Select(child => child.OnClicked).Merge().Subscribe(_ => {
// いずれかの子供のClickStreamが発行された
}).AddTo(this);
}
}
class ChildHoge : MonoBehaviour{
[SerializeField]
UIButton btn;
public IObservable<Unit> OnClicked{
get; private set;
}
void Awake(){
OnClicked = btn.OnClick.AsObservable();
}
}
- スタミナの回復時間などで前後時間を比較した計算する
例えばゲームのスタミナの回復時間を表示する箇所。
次の最大回復時間をサーバーから受け取って、現在時刻と比較するのが一般的だと思う。
ちょっと拡張して、次の回復までの時間、最大までの時間、現在の時間をRxで計算してみた
DateTime GetCurrentTime(){
// なんか
return DateTime.Now;
}
// 初期化済
ReadOnlyReactiveProperty<int> TimeToMax;
ReactiveProperty<int> timeToMax;
ReactiveProperty<int> present;
ReadOnlyReactiveProperty<int> Present;
ReactiveProperty<int> intervalTime;
ReadOnlyReactiveProperty<int> IntervalTime;
ReactiveProperty<int> maxPoint;
ReadOnlyReactiveProperty NextPointRecoverTime;
// 通信するたびに最大回復までの時刻が更新される
void Init(int timeToMax, int presentTime, int intervalTime){
//最大までの時間(秒)
TimeToMax = timeToMax.Select(ttm =>
Observable.Timer(TimeSpan.FromSeconds(0),TimeSpan.FromSeconds(1))
.Select(_ => GetCurrentTime()).Buffer(2, 1)
.Select(buf => (buf[1] - buf[0]).TotalSeconds)
.Scan((double)0, (prev, current) => prev + current)
.DistinctUntilChanged()
.StartWith(0)
.Select(t => Mathf.RoundToInt(t)
).Switch()
.ToReadonlyReactiveProperty();
// 現在のスタミナ値
Present = present
.CombineLatest(TimeToMax.Select(sec => Mathf.FloorToInt((TimeToMax.Select(sec => Mathf.FloorToInt(MaxPoint.Value - (float)sec / (float)Interval.Value)), (present, max) => Mathf.Max(p1, p2))
.DistinctUntilChanged()
.ToReadOnlyReactiveProperty();
NextPointRecoverTime = this.TimeToMax.Select(sec => IntervalTime.Value == 0 ? 0 : sec % Interval.Value).ToReadOnlyReactiveProperty();
this.maxPoint.Value = maxPoint;
this.interval.Value = interval;
this.timeToMax.Value = timeToMax;
}
- ストリームをmergeするけど、Streamごとに違う処理をはさみたい.
yes おされたときとno押された時に違う処理をした後に共通処理したい。(FinallyはOnError時にも引っかかってしまうのでそれでは困るケース)
HogePopup popup;
popup.OnYesClicked.SelectMany(_ => API.PostYesData().Select(_ => UniRx.Unit))
.Merge(popup.OnNoClicked.SelectMany(_ => API.PostNo().Select(_ => UniRx.Unit))
.Subscribe(_ => {// 共通処理})
.AddTo(this);
たとえば、自動ページングするリストビューなど子供の要素数が変化するもの。
子供要素が変化が起こるたびにクリックストリームを更新したい
ReactiveCollection<HogeComponent> collection;
// 子供要素が変化するたびにきちんとcollectionを同期する処理がどっかに実装されてる
void Awake(){
collection = new RactiveCollection<HogeComponent>();
// hotにしたいかな
var stream = collection.OnCountChanged().Select(_ => collection.Value.OnClicked).Switch().Publish();
stream.Connect();
stream.Subscribe(_ => {
// なんか
});
}