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

Resolved Possible BUG - IPointerClickHandler.OnPointerClick inconsistent behaviour

Discussion in 'Input System' started by MikaLikeABoss, Apr 19, 2022.

  1. MikaLikeABoss

    MikaLikeABoss

    Joined:
    Nov 23, 2019
    Posts:
    3
    Because my current project is more a simulator than a game I'm handling all input by means of the Event System. I mean, I'm using IPointerClickHandler for clicks and double clicks, IDragHandler for map navigation, IScrollHandler for zooming, etc.

    I'm having success with everything except IPointerClickHandler.

    My double click detection is inconsistent. And I don't understand why. Per documentation, PointerEventData.clickCount should suffice.

    But Sometimes it catches the double clicks, and some times it fails and detect only single click. It even may fail when using my gamer mouse integrated double click button (a special button in the left side that when pressed sends double clicks).

    Also, I tried to adjust public fields in the Event System of the Scene to tune values like
    DragThreshold
    ,
    InputActionPerSecond
    and
    RepeatDelay
    . My current values are:

    Code (CSharp):
    1. DragThreshold = 1
    2. InputActionPerSecond = 50
    3. RepeatDelay = 0.2
    My current double click detection code:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.EventSystems;
    5.  
    6. public class CanvasControl : MonoBehaviour, IPointerClickHandler, IBeginDragHandler, IDragHandler, IScrollHandler
    7. {
    8.     GameObject MainCam = null;
    9.  
    10.     // Start is called before the first frame update
    11.     void Start()
    12.     {
    13.         MainCam = GameObject.Find("Main Camera");
    14.     }
    15.  
    16.     // Update is called once per frame
    17.     void Update()
    18.     {
    19.    
    20.     }
    21.  
    22.     float lastTimeClicked = 0f;
    23.  
    24.     public void OnPointerClick(PointerEventData pointerEventData)
    25.     {
    26.         if (pointerEventData.button == 0)
    27.         {
    28.             float time = Time.time - lastTimeClicked;
    29.             if (time <= 0.5f || pointerEventData.clickCount > 1)
    30.             {
    31.                 MainCam.GetComponent<MapInput>().FireRayQuery = true;
    32.                 Debug.Log("Double Click at " + Time.time);
    33.             } else
    34.             {
    35.                 lastTimeClicked = Time.time;
    36.                 Debug.Log("Single Click at " + Time.time);
    37.             }
    38.         }
    39.  
    40.         /*if (pointerEventData.clickCount == 2)
    41.         {
    42.             MainCam.GetComponent<MapInput>().FireRayQuery = true;
    43.             Debug.Log("Double Click at " + Time.time);
    44.         }*/
    45.     }
    46.  
    47.     Vector2 lastDragPos = new Vector2();
    48.  
    49.     public void OnDrag(PointerEventData eventData)
    50.     {
    51.         Vector2 delta = eventData.position - lastDragPos;
    52.  
    53.         Debug.Log("delta = " + delta);
    54.  
    55.         float orthogonal_size = MainCam.GetComponent<Camera>().orthographicSize * 2f;
    56.  
    57.         // convert to Main Camera orthogonal coordinates, (-10, +10) for the default zoom, in the vertical axis
    58.         delta.x = delta.x / (float)Screen.height * orthogonal_size * -1f;
    59.         delta.y = delta.y / (float)Screen.height * orthogonal_size * -1f;
    60.  
    61.         Debug.Log("delta = " + delta);
    62.  
    63.         MainCam.transform.Translate(delta.x, delta.y, 0f);
    64.  
    65.         lastDragPos = eventData.position;
    66.     }
    67.  
    68.     public void OnBeginDrag(PointerEventData eventData)
    69.     {
    70.         lastDragPos = eventData.position;
    71.     }
    72.  
    73.     public void OnScroll(PointerEventData eventData)
    74.     {
    75.         float osize = MainCam.GetComponent<Camera>().orthographicSize;
    76.  
    77.         osize += eventData.scrollDelta.y;
    78.  
    79.         if (osize > 50f)
    80.             osize = 50f;
    81.  
    82.         if (osize < 4f)
    83.             osize = 4f;
    84.  
    85.         MainCam.GetComponent<Camera>().orthographicSize = osize;
    86.     }
    87. }
    88.  
     
    Last edited: Apr 19, 2022
    Ripclaw52 likes this.
  2. MikaLikeABoss

    MikaLikeABoss

    Joined:
    Nov 23, 2019
    Posts:
    3
    I have found that detecting double clicks is more reliable in your Update() implementation.

    It seems the Event System doesn't call
    OnPointerClick
    immediately, it may be waiting some milliseconds to see if the second click comes. This, mixed with some slower frames during your unoptimized game, may result in inconsistent double click detection.

    Solution: If you don't like to copy paste the couroutine based solution that you can find here in forum or in stackexchange, then you only need to detect double clicks in your
    MonoBehaviour.Update
    . Microsoft says 500 milliseconds between clicks is a safe threshold to consider them a double click.

    Also,
    DragThreshold = 1
    is not a good value. I tried it only while trying random things to solve my problem.
     
    Ripclaw52 likes this.