[Solved] How to detect double tap on ui button and change interval.

Thanks for good model code. My modification below where flag for readyForDoubleTap is not actually needed but just clean tap calculation after interval

    float interval = 0.5f;
    int tap;

public void OnPointerClick(PointerEventData eventData)
    {
        tap++;

        if (tap == 1)
        {
            StartCoroutine(DoubleTapInterval());
        }

        else if (tap > 1)
        {
            // Do stuff
            
            // clean tap calculation
            tap = 0;
        }
    }


Enumerator DoubleTapInterval()
    {
        yield return new WaitForSeconds(interval);
        this.tap = 0;
    }

I have a different approach which I think is slightly closer to standards. Hope it helps!

This doesn’t use the incremental click because (as mentioned) that doesn’t stick to timing standards, and ALSO, it’s possible to get a false positive double click because it’s consecutive clicks anywhere, not just on the object being clicked. This means that your first click could be on object A, and your second click on object B, and if it’s fast enough, it’d still count as a double click. It’s an edgecase, admittedly, but that doesn’t happen as standard on say, windows.

The other thing to note here is that double clicks don’t occur on the “click” event (which is when you press then release on the same object). The occur on the second consecutive pointer down event within 500ms of the last pointer down event.

So basically, what I do here is record the object that is clicked on by the click event (by using the pointerCurrentRaycast.gameObject). If I click down again, I check if it’s the same object being clicked as last time. If it is, and the time since last click (in unscaled time!!) is less than a half a second, I can trigger the double click.

The “LASTPOINTERDOWNOBJECT” is static, and maybe you want to record one of these for each mouse click’s
InputButton, so that left, then right click doesn’t make a double click.

Might get around to codifying this into an IPointerDoubleClick event that you can Execute up the hierarchy, but that’ll mean extending out an event system first.

using UnityEngine;
using UnityEngine.EventSystems;

public class UICard : MonoBehaviour, IPointerDownHandler
{
    const float doubleClickTime = 0.5f;//Wish I could trivially plum this into the system's doubleclick time.
    private static GameObject LASTPOINTERDOWNOBJECT = null;//Need to record the last click event's object, so that double clicking doesn't occur when skipping across objects (avoid accidental double click). I tried looking through PointerEventData, but none of the values I expected came back with a record of the previously clicked/hovered object.
   
    public void OnPointerDown(PointerEventData eventData)
    {
        float timeSinceLastClick = Time.unscaledTime - eventData.clickTime;//Note use of unscaled time. I've tested with Time.timeScale = 0.0f; and this still works.
        bool bSameObjectClicked = LASTPOINTERDOWNOBJECT == eventData.pointerCurrentRaycast.gameObject;
       
        if ( timeSinceLastClick < doubleClickTime && bSameObjectClicked)
        {
            Debug.Log("DoubleClick pressed!");
        }

        LASTPOINTERDOWNOBJECT = eventData.pointerCurrentRaycast.gameObject;
    }
}
1 Like

You might try this. The timing is exact and there isn’t the issue with needing to use IPointerDownHandler if you don’t want to:

float lastClick = 0f;
float interval = 0.5f;

public void OnClickAction()
{

if ((lastClick+interval)>Time.time)
{
Debug.Log(“//is a double click”);
lastClick = 0f;
}
else
{
lastClick = Time.time;
StartCoroutine(SingleClick());
}

}

IEnumerator SingleClick() {
yield return new WaitForSeconds(interval);
if(lastClick != 0f)
{
Debug.Log(“//is a single click”);
lastClick = 0f;
}

}