UniRxとuGUIの組み合わせは非常に使いやすいのですが、もっと使いやすくする為に拡張メソッドを使用して、より使いやすくしてみました。
ボタンが連打されたときは一回のみ判定したい、もしくはちょっと間が空いてからボタンを有効にしたい、ボタンの長押しを検知したいといった要望があった為実装してみました。
ボタンを一度のみ、もしくは指定時間おいたもののみ判定する
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public static IObservable<Unit> OnClickIntentAsObservable(this Button button, ButtonClickIntent intent = ButtonClickIntent.Normal) { var clickObservable = button.onClick.AsObservable() .Where(_ => Input.touchSupported == false || (Input.touchSupported == true & Input.touches.Length <= 1)); switch (intent) { case ButtonClickIntent.OnlyOneTap: return clickObservable.First(); case ButtonClickIntent.IntervalTap: return clickObservable.ThrottleFirst(TimeSpan.FromSeconds(0.5f)); case ButtonClickIntent.Normal: default: return clickObservable; } } |
ButtonClickIntentをenumで定義しています。
1 2 3 4 5 |
public enum ButtonClickIntent { Normal, OnlyOneTap, IntervalTap, } |
OnlyOneTap(一度のみ)の場合はFirst()で連打されたものの中で最初だけを取得します。
IntervalTap(一定時間を空ける)場合は指定した時間(コードでは0.5秒)の間は処理を受け付けないようにしています。
ボタンが長押しされたということを判定する
1 2 3 4 5 6 7 8 9 10 11 |
public static IObservable<long> OnHoldAsObservable(this Button button, double ms = 350, Action releaseEvent = null) { return button.OnPointerDownAsObservable() .SelectMany(_ => Observable.Timer(TimeSpan.FromMilliseconds(ms))) .TakeUntil(button.OnPointerUpAsObservable() .Do(_ => { if (releaseEvent != null) releaseEvent(); })) .RepeatUntilDestroy(button) .AsObservable(); } |
ボタンが押されて(OnPointerDownAsObservable)から、離される(OnPointerUpAsObservable)までの時間をTimerで計測し、所定の時間が経過していたら長押しされたという判定にしています。