はじめに
この記事では次のAssetを利用しています。
DoozyUIで長押しを検知する
DoozyUIを使うと、かなり簡単にボタンの長押しを検知することができます。
これを応用することで、複雑そうな挙動もかなり簡単に実現することができます。
長押しイベントをまず取得する
DoozyUIで「長押し」が検知できるようにしてみましょう。
やり方としては次の2ステップ。
1. InspectorViewからOnLongClickを有効にする
UIButton
コンポーネントのOnLongClick
の左側のトグルを押して有効化します。
これを有効にしないとスクリプトからイベントが取得できません。
なお、Register Interval
の部分が長押し判定されるまでの秒数です。
2. スクリプトからイベントを取得する
こんな感じでOK。
using Doozy.Engine.UI;
using UniRx;
using UnityEngine;
public class LongClickSample : MonoBehaviour
{
/// <summary>
/// DoozyUIのUIButtonコンポーネント
/// </summary>
[SerializeField] private UIButton _uiButton;
void Start()
{
// 長押し
_uiButton
.OnLongClick
.OnTrigger
.Event
.AsObservable()
.Subscribe(_ =>
{
Debug.Log("OnLongClick!");
}).AddTo(this);
// uGUIのButtonはプロパティからアクセス可能
_uiButton.Button.OnClickAsObservable().Subscribe(_ => { }).AddTo(this);
}
}
拡張メソッド経由にする
Observable
化するのがちょっと冗長なので、次のような拡張メソッドを用意する。
using System;
using Doozy.Engine.UI;
using UniRx;
namespace Samples.Utils
{
public static class UIButtonBehaviorExtension
{
public static IObservable<Unit> AsObservable(this UIButtonBehavior b)
{
return b.OnTrigger.Event.AsObservable();
}
}
}
そうすると拡張メソッド経由で呼び出せるのでちょっと記述が減る。
using Doozy.Engine.UI;
using Samples.Utils;
using UniRx;
using UnityEngine;
public class LongClickSample : MonoBehaviour
{
/// <summary>
/// DoozyUIのUIButtonコンポーネント
/// </summary>
[SerializeField] private UIButton _uiButton;
void Start()
{
// 長押し
_uiButton
.OnLongClick
.AsObservable() //拡張メソッド
.Subscribe(_ => { Debug.Log("OnLongClick!"); }).AddTo(this);
}
}
長押しをしている間、一定間隔でイベントを発行させる
ボタンを押しっぱなしにしている間は一定間隔でイベントを発行できると便利です。
この機能があれば、たとえば「長押しをしている間は連続で数字が変化する」といった機能が簡単に実装できるようになります。
作り方
1. InspectorViewからOnPointerUpを有効にする
ボタンを離したときにイベントを止める必要があるので、OnPointerUpイベントが発行されるようにしておきます。
2. 拡張メソッド用意する
次のような拡張メソッドを用意します。
using System;
using Doozy.Engine.UI;
using UniRx;
namespace Samples.Utils
{
public static class UIButtonExtension
{
public static IObservable<Unit> OnLongPressAsObservable(this UIButton b, TimeSpan timeSpan)
{
var longPress = b.OnLongClick.AsObservable();
var up = b.OnPointerUp.AsObservable();
return longPress.Take(1)
.ContinueWith(_ => Observable.Interval(timeSpan).TakeUntil(up))
.AsUnitObservable()
.RepeatSafe();
}
}
}
3. OnLongPressAsObservableを使う
あとは拡張メソッド経由でObservable
を取得すればOKです。
using System;
using Doozy.Engine.UI;
using Samples.Utils;
using TMPro;
using UniRx;
using UnityEngine;
public class UpDownSample : MonoBehaviour
{
[SerializeField] private UIButton _upButton;
[SerializeField] private UIButton _downButton;
[SerializeField] private TextMeshProUGUI _text;
private IntReactiveProperty Count = new IntReactiveProperty(0);
private void Start()
{
// 変化した数値をTextに反映
Count.Subscribe(x => _text.text = x.ToString()).AddTo(this);
//----------------------------
// 長押しのUp!!!
_upButton
// 拡張メソッド, 引数で長押し中に発行されるイベントの間隔を指定できる
.OnLongPressAsObservable(TimeSpan.FromMilliseconds(100))
.Subscribe(_ => Count.Value++).AddTo(this);
// 長押しのDown!!!
_downButton
// 拡張メソッド, 引数で長押し中に発行されるイベントの間隔を指定できる
.OnLongPressAsObservable(TimeSpan.FromMilliseconds(100))
.Subscribe(_ => Count.Value--).AddTo(this);
// ----------------------------
// 単発 Up
_upButton.Button.OnClickAsObservable()
.Subscribe(_ => Count.Value++).AddTo(this);
// 単発 Down
_downButton.Button.OnClickAsObservable()
.Subscribe(_ => Count.Value--).AddTo(this);
}
}
まとめ
Doozy UIを使うとかなり簡単に各種イベントが取得できるようになります。
そこにUniRxを組み合わせると、だいたいのことは少ないコード量で実現できるのでいいですね。