Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

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

Discussion in 'UGUI & TextMesh Pro' started by tranos, Jan 7, 2015.

  1. tranos

    tranos

    Joined:
    Feb 19, 2014
    Posts:
    180
    Is it possible to detect double click as with guitexture ( input.GetTouch(i).tapcount==2 ) ?
    Thank you in advance.
     
    denny017 likes this.
  2. phil-Unity

    phil-Unity

    Unity UI Lead Developer

    Joined:
    Nov 23, 2012
    Posts:
    1,226
    There is a click count in the PointerEventData.
     
  3. tranos

    tranos

    Joined:
    Feb 19, 2014
    Posts:
    180
    Is there an example so I can see PointerEventData in code ?
     
  4. phil-Unity

    phil-Unity

    Unity UI Lead Developer

    Joined:
    Nov 23, 2012
    Posts:
    1,226
    It'd be something like this. I dont have a better example.

    public void OnPointerClick(PointerEventData eventData)
    {
    eventData.clickCount;
    }
     
    AbgaryanFX likes this.
  5. tranos

    tranos

    Joined:
    Feb 19, 2014
    Posts:
    180
    Could be something like this and attach the script on my image or I got it all wrong?


    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.EventSystems;
    4.  
    5. public class a_clickcount : MonoBehaviour, IPointerClickHandler
    6. {
    7.     int tap;
    8.  
    9.  
    10.     public void OnPointerClick(PointerEventData eventData)
    11.     {
    12.         tap = eventData.clickCount;
    13.  
    14.         if (tap == 2)
    15.         {
    16.             // do something
    17.         }
    18.  
    19.     }
    20. }
     
    Last edited: Feb 10, 2015
  6. phil-Unity

    phil-Unity

    Unity UI Lead Developer

    Joined:
    Nov 23, 2012
    Posts:
    1,226
    should be correct.
     
  7. tranos

    tranos

    Joined:
    Feb 19, 2014
    Posts:
    180
    Doesn't work... Is there a way to implement it in the event system in drop down options (OnDoubleClick) ?
     
  8. tranos

    tranos

    Joined:
    Feb 19, 2014
    Posts:
    180
    I found why it didn't work. "IPointerClickHandler " was missing.
     
  9. erictang

    erictang

    Joined:
    Jul 28, 2012
    Posts:
    15
    how can I control the click checking interval ?
     
  10. tranos

    tranos

    Joined:
    Feb 19, 2014
    Posts:
    180
    You can set a timer when first tap is registered.
     
  11. erictang

    erictang

    Joined:
    Jul 28, 2012
    Posts:
    15
    i meant two tap interval,to trigger double click event
     
  12. tranos

    tranos

    Joined:
    Feb 19, 2014
    Posts:
    180
    You could do something like this maybe:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.EventSystems;
    4.    
    5.     public class TapTest : MonoBehaviour, IPointerClickHandler
    6. {
    7.     int tap;
    8.     float interval = 5f;
    9.     bool readyForDoubleTap;
    10.     public void OnPointerClick(PointerEventData eventData)
    11.     {
    12.         tap ++;
    13.  
    14.         if (tap ==1)
    15.         {
    16.             //do stuff
    17.  
    18.             StartCoroutine(DoubleTapInterval() );
    19.         }
    20.  
    21.         else if (tap>1 && readyForDoubleTap)
    22.         {
    23.             //do stuff
    24.  
    25.  
    26.             tap = 0;
    27.             readyForDoubleTap = false;
    28.         }
    29.     }
    30.  
    31.     IEnumerator DoubleTapInterval()
    32.     {  
    33.         yield return new WaitForSeconds(interval);
    34.         readyForDoubleTap = true;
    35.     }
    36. }
     
  13. MattRix

    MattRix

    Joined:
    Aug 23, 2011
    Posts:
    121
    For the record, the actual click time in the Unity event system is hardcoded as 0.3 seconds (instead of 0.5 which is the default in Windows). I have no idea why they chose such a fast time and hardcoded it. The obvious-but-annoying solution is to create a new input module that is just a copy of the normal one but with that value changed.
     
    EZaca and Palineto like this.
  14. Cleverlie

    Cleverlie

    Joined:
    Dec 23, 2013
    Posts:
    219
    hi @MattRix can you give a link to where did you get that info? because if it is like that I would like to customize the input module to work with 0.5 instead of the hardcoded 0.3, but I'm not finding any property or field to do so in my extendedStandaloneInput class which inherits from standaloneInputModule.
     
  15. methos5k

    methos5k

    Joined:
    Aug 3, 2015
    Posts:
    8,712
    You can find it here (just search for clickCount): https://bitbucket.org/Unity-Technol...Module.cs?at=5.2&fileviewer=file-view-default
     
  16. JuanGuzmanH

    JuanGuzmanH

    Joined:
    Feb 8, 2018
    Posts:
    73
    There is a much simpler and efficient approach.
    Just save the last click time and compare in the next click.
    Something like
    Code (CSharp):
    1. float lastClick = 0f;
    2. float interval = 0.4f;
    3.     public void OnPointerClick(PointerEventData eventData)
    4.     {
    5.       if ((lastClick+interval)>Time.time)
    6.           {//is a double click }
    7.       else
    8.           {//is a single click }
    9.       lastClick = Time.time;
    10.     }
    11.  
     
  17. rainnedev

    rainnedev

    Joined:
    Mar 6, 2015
    Posts:
    4
    Thanks for this -- the logic inside is very very helpful and adaptable to any way. :)
     
  18. rowanchin

    rowanchin

    Joined:
    Mar 12, 2019
    Posts:
    1
    if i do a double click, the single click function will still occur. what can i do to not make that happen?
     
  19. sahilushaikh6

    sahilushaikh6

    Joined:
    Dec 4, 2018
    Posts:
    3
     
  20. Abubakarzahid7

    Abubakarzahid7

    Joined:
    Feb 14, 2020
    Posts:
    1
    work for me with some changes
     
  21. Heemu

    Heemu

    Joined:
    Dec 23, 2014
    Posts:
    1
    Thanks for good model code. My modification below where flag for readyForDoubleTap is not actually needed but just clean tap calculation after interval

    Code (CSharp):
    1.  
    2.     float interval = 0.5f;
    3.     int tap;
    4.  
    5. public void OnPointerClick(PointerEventData eventData)
    6.     {
    7.         tap++;
    8.  
    9.         if (tap == 1)
    10.         {
    11.             StartCoroutine(DoubleTapInterval());
    12.         }
    13.  
    14.         else if (tap > 1)
    15.         {
    16.             // Do stuff
    17.            
    18.             // clean tap calculation
    19.             tap = 0;
    20.         }
    21.     }
    22.  
    23.  
    24. Enumerator DoubleTapInterval()
    25.     {
    26.         yield return new WaitForSeconds(interval);
    27.         this.tap = 0;
    28.     }
     
  22. AubreyH

    AubreyH

    Joined:
    May 17, 2018
    Posts:
    18
    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.


    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.EventSystems;
    3.  
    4. public class UICard : MonoBehaviour, IPointerDownHandler
    5. {
    6.     const float doubleClickTime = 0.5f;//Wish I could trivially plum this into the system's doubleclick time.
    7.     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.
    8.    
    9.     public void OnPointerDown(PointerEventData eventData)
    10.     {
    11.         float timeSinceLastClick = Time.unscaledTime - eventData.clickTime;//Note use of unscaled time. I've tested with Time.timeScale = 0.0f; and this still works.
    12.         bool bSameObjectClicked = LASTPOINTERDOWNOBJECT == eventData.pointerCurrentRaycast.gameObject;
    13.        
    14.         if ( timeSinceLastClick < doubleClickTime && bSameObjectClicked)
    15.         {
    16.             Debug.Log("DoubleClick pressed!");
    17.         }
    18.  
    19.         LASTPOINTERDOWNOBJECT = eventData.pointerCurrentRaycast.gameObject;
    20.     }
    21. }
    22.  
     
    FifthLord likes this.