実施内容:
Unity 独自の Button コンポーネントを拡張して、元のクリック イベントに基づいてダブルクリックと長押しの効果を実現します。
コードの詳細な説明:
- クリックイベントの処理:
singleClickEnabled
スイッチを通じてクリック イベントを有効にするかどうかを制御します。OnPointerClick
メソッドでは、ボタンのアクティブ化状態と対話可能状態に従ってクリック イベントを実行します。- Unity の Profiler API を使用してマーカーを追加し、ボタンのクリック イベント コールバックをトリガーします。
- ダブルクリックイベントの処理:
doubleClickEnabled
スイッチを通じてダブルクリック イベントを有効にするかどうかを制御します。OnPointerClick
メソッドでは、クリック数を記録し、ダブルクリック時間のしきい値に基づいてダブルクリック イベントをトリガーするかどうかを決定します。- ダブルクリックが検出された場合は、プロファイラー タグを追加し、ダブルクリック イベント コールバックをトリガーし、クリック数をリセットします。
- 長押しイベント処理:
longPressEnabled
スイッチを使用して、長押しイベントを有効にするかどうかを制御します。OnPointerDown
メソッドで、押した時間を記録し、長押し状態をマークします。OnPointerUp
メソッドで、長押し状態をリセットします。- 定期的に長押しを検出するには使用
Update
メソッドを使用します。長押し時間のしきい値に達すると、長押しイベント コールバックがトリガーされます。
- イベントコールバック:
ButtonClickedEvent
インスペクターで構成できるタイプのイベント コールバックを使用- クリック、ダブルクリック、長押しのイベント コールバックを提供します。これらはインスペクターまたはコードを通じて設定できます。
完全なコードは次のとおりです。
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
using UnityEngine.UI;
public class ButtonExtension : Button
{
#region 单机双击相关
public bool singleClickEnabled = true;
public bool doubleClickEnabled = false;
public float doubleClickTime = 0.3f;
private float lastClickTime = float.NegativeInfinity;
private int clickCount = 0;
[FormerlySerializedAs("onDoubleClick")]
[SerializeField]
private ButtonClickedEvent doubleClickEvent = new ();
public ButtonClickedEvent onDoubleClick
{
get => doubleClickEvent;
set => doubleClickEvent = value;
}
public override void OnPointerClick(PointerEventData eventData)
{
if(!IsActive() && !interactable)
return;
if (singleClickEnabled)
{
UISystemProfilerApi.AddMarker("Button.onClick", this);
onClick?.Invoke();
Debug.LogError("单击");
}
if (doubleClickEnabled)
{
clickCount++;
if (clickCount >= 2)
{
if (Time.realtimeSinceStartup - lastClickTime < doubleClickTime)
{
UISystemProfilerApi.AddMarker("Button.onDoubleClick", this);
onDoubleClick?.Invoke();
Debug.LogError("双击");
lastClickTime = float.NegativeInfinity;
clickCount = 0;
}
else
{
clickCount = 1;
lastClickTime = Time.unscaledTime;
}
}
else
{
lastClickTime = Time.unscaledTime;
}
}
}
#endregion
#region 长按相关
public bool longPressEnabled = false;
private float lastPressTime = 0;
public float minPressTime = 0.5f;
private bool isPressing = false;
private bool hasInvokedLongPress = false;
[FormerlySerializedAs("onLongPress")]
[SerializeField]
private ButtonClickedEvent longPressEvent = new();
public ButtonClickedEvent onLongPress
{
get => longPressEvent;
set => longPressEvent = value;
}
public override void OnPointerDown(PointerEventData eventData)
{
base.OnPointerDown(eventData);
if (longPressEnabled)
{
hasInvokedLongPress = false;
isPressing = true;
lastPressTime = Time.unscaledTime;
}
}
public override void OnPointerUp(PointerEventData eventData)
{
base.OnPointerUp(eventData);
isPressing = false;
hasInvokedLongPress = false;
}
private void Update()
{
DealLongPress();
}
private void DealLongPress()
{
if(hasInvokedLongPress) return;
if (isPressing)
{
if (Time.unscaledTime - lastPressTime >= minPressTime)
{
UISystemProfilerApi.AddMarker("Button.onLongPress", this);
onLongPress?.Invoke();
hasInvokedLongPress = true;
Debug.LogError("执行长按事件");
}
}
}
#endregion
}
新しいプロパティを [インスペクター] パネルに追加します。具体的なコードは次のとおりです。
using UnityEngine;
namespace UnityEditor.UI
{
[CustomEditor(typeof(ButtonExtension), true)]
[CanEditMultipleObjects]
public class ButtonExInspector : SelectableEditor
{
private ButtonExtension buttonExtension;
SerializedProperty onDoubleClickProperty;
SerializedProperty onClickProperty;
SerializedProperty onLongPressProperty;
protected override void OnEnable()
{
base.OnEnable();
onDoubleClickProperty = serializedObject.FindProperty("doubleClickEvent");
onClickProperty = serializedObject.FindProperty("m_OnClick");
onLongPressProperty = serializedObject.FindProperty("longPressEvent");
}
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
serializedObject.Update();
buttonExtension = (ButtonExtension)target;
EditorGUILayout.Space();
buttonExtension.singleClickEnabled = EditorGUILayout.Toggle("启用单击", buttonExtension.singleClickEnabled);
if (buttonExtension.singleClickEnabled)
{
buttonExtension.doubleClickEnabled = false;
buttonExtension.longPressEnabled = false;
EditorGUILayout.PropertyField(onClickProperty);
}
buttonExtension.doubleClickEnabled = EditorGUILayout.Toggle("启用双击", buttonExtension.doubleClickEnabled);
if (buttonExtension.doubleClickEnabled)
{
buttonExtension.doubleClickTime = EditorGUILayout.FloatField("双击间隔", buttonExtension.doubleClickTime);
buttonExtension.singleClickEnabled = false;
buttonExtension.longPressEnabled = false;
EditorGUILayout.PropertyField(onDoubleClickProperty);
}
buttonExtension.longPressEnabled = EditorGUILayout.Toggle("启用长按", buttonExtension.longPressEnabled);
if(buttonExtension.longPressEnabled)
{
buttonExtension.minPressTime = EditorGUILayout.FloatField("长按时间", buttonExtension.minPressTime);
buttonExtension.singleClickEnabled = false;
buttonExtension.doubleClickEnabled = false;
EditorGUILayout.PropertyField(onLongPressProperty);
}
serializedObject.ApplyModifiedProperties();
if(GUI.changed)
EditorUtility.SetDirty(target);
}
}
}