⏳
UniRxでuGUIのボタン長押しを取る
UniRxでuGUIのボタン長押しを取る
button.OnPointerDownAsObservable().Select(_ => true)
.Merge(button.OnPointerUpAsObservable().Select(_ => false))
.Throttle(TimeSpan.FromSeconds(1))
.Where(b => b)
.AsUnitObservable()
.Subscribe(OnLongClick);
これで1秒の長押しが取れます。
解説
コード
UniRx
って解説がないと何やってるかわかんない……! となることが多いので、一行ずつコメントを挟みます。
// OnPointerDownをtrueに変換
button.OnPointerDownAsObservable().Select(_ => true)
// OnPointerUpをfalseに変換して合成
// この後には押した時にtrueが、離した時にfalseが流れるようになる
.Merge(button.OnPointerUpAsObservable().Select(_ => false))
// 1秒間新しい値が来なかったら最後に来た値を流す
.Throttle(TimeSpan.FromSeconds(1))
// trueだけを流す
.Where(b => b)
// このboolはどうでもいい値なのでUnitにする
.AsUnitObservable()
// 長押しを購読!!!
.Subscribe(OnLongClick);
いちおう書いておくとSubscribeはこんな感じ
private void OnLongClick(Unit _)
{
}
図
キモはThrottle
です。これは指定された間新しい値が流れてこなかったら、そのときに最後に流れてきた値を流します。
今回のようにbool
を流すStreamの場合は以下のような動きをするわけです。
○をtrue、✘をfalse、□を一定時間として見てください。
falseのパターン
一定時新しい値が来なかったら最後に来た値を流す、つまりこの図だと「最後にボタンを離した後、新しくボタンを押していない」ということになるのでThrottle
からfalseが流れてくるわけです。
trueのパターン
この場合だと最後にtrueが流れてくる、つまり「ボタンを押した後、一定時間ボタンを離していない= 長押ししている 」ということになります。
まとめ
標準で長押し実装しろ!!!!!!!!!!!!!!! という話がまずありますね![1]
最初はMerge
だけしてPointerEventDataのパラメータを見て判断しようとしていて、確かに違いはあったんですが、マルチプラットフォームで裏切ってくるタイプに見えたのでやめました。
何を意味しているのかいまいちわからないプロパティに頼るくらいなら自分で設定したbool
を信じる。だいじ。
長押しって需要あると思うのですが、ネットに落ちてるやつはどれもなんか納得行かないな? みたいな感じだったので新しく考えました。自分にはわかりやすいなので満足です。
おしまい。
参考
-
需要めちゃくちゃある……めちゃくちゃある! と思いましたがEventSystem周りの更新には多大な勇気がいるとかそういう話なんですかね。謎。 ↩︎
Discussion