Mouse double click without single click

Hey guys,
I made a script that detects, single click, double click and drag.
The problem I have is when I double click it also executes a single click.
Any ideas? I spend two days thinking about it :frowning:

There are examples using Coroutine or tap counter.

Need a little help.

 // Update is called once per frame
    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            startTime = Time.time;
            timeSinceLastClick = Time.time - lastClickTime;

            if (timeSinceLastClick <= 0.2f)
            {
                Debug.Log("Double click");
            }
           
            lastClickTime = Time.time;
        }

        if (Input.GetMouseButtonUp(0))
        {
            if (Time.time - startTime <= touchDelay)
            {
                Debug.Log("Single click");
            }
        }

        if (Input.GetMouseButton(0))
        {
            Debug.Log("Drag");
        }
    }

You need a simple state machine whose logic looks something like this:

State: IDLE
In the idle state, if the player clicks, you can transition to the WAITING state.

State: WAITING
In the waiting state, you need to count the elapsed time and wait for a click.

  • If a click comes before the maximum time for a double click has elapsed, perform a double click action and transition to the IDLE state
  • If the elapsed time exceeds the maximum time for a double click, perform a single click action, and transition to the IDLE state
1 Like

Can I do it with simple bool and if statements?
Have you got an example?

I will try to put your words into code. It kinda make sense …

You need some kind of bool to check

From a glance, looks like it’s because

if (Input.GetMouseButtonUp(0))
{
if (Time.time - startTime <= touchDelay)
{
Debug.Log(“Single click”);
}
}


It's counting how long the click is pressed down, an independent logic from double click. I could be wrong.

I think something like this could work. *(Apologies for writing the comments on the same line. Didn't realize they would look this way here)*

```csharp
 [SerializeField] float touchDelay = 0.25f; //The maximumAmount of time between two clicks to consider it a double click
    private float doubleClickTime; //the next click have to be within this Time.time+touchdelay to be a double click
    private bool clickTriggered = true; //if the double click isn't triggered within this time, trigger the single click

    [SerializeField] float dragThreshHold = 0.5f; //After this amount of time, a click is considered a drag
    private float dragTime; //how long the current click is held down
    private bool wasDragging = false; //To make sure get mouse button up do not trigger a click after drag

    void Update()
    {
        //when the click is finished
        if (Input.GetMouseButtonUp(0))
        {
            //the click finished within the max delay
            if (Time.time <= doubleClickTime)
            {
                Debug.Log("Double click");
                clickTriggered = true;
            }
            else //the click wasn't finished within the double click delay
            {
                //if the click was dragging, don't trigger clicks
                if (wasDragging)
                {
                    wasDragging = false;
                }
                else // the first click
                {
                    clickTriggered = false;
                    doubleClickTime = Time.time + touchDelay;
                }
            }
        }
        else if (clickTriggered == false && wasDragging == false)
        {
            //the second click didnt happen within the delay, just trigger the first one
            if (Time.time > doubleClickTime)
            {
                Debug.Log("Single click");
                clickTriggered = true;
            }
        }

        //button held down
        if (Input.GetMouseButton(0))
        {
            //held down for long
            if (dragTime > dragThreshHold)
            {
                wasDragging = true;
                clickTriggered = true;
                Debug.Log("Drag");
            }
            else
            {
                dragTime += Time.deltaTime;
            }
        }
        else
        {
            dragTime = 0; //reset the value if it isn't held down
        }
    }
1 Like

Hi @FerdowsurAsif yes, you are correct this is because of this line. So I need some sort of bool. Saying the second click hasn’t happened make a single click.

It seems your script should work, the only problem I see is there is going to be a delay in a single click.

A delay in a single click is not really avoidable when making a system like this. If there was no delay, it would be impossible to distinguish between a single click and merely the first click of the double click, as we cannot tell if a second click is coming in the near future.

The only way you could avoid a delay is if the single-click action was somehow able to be rolled back cleanly when the second click arrives.

1 Like

Yes. Unfortunately.

One other approach could be always triggering the single click.
Then not triggering the single click on the double click.

So, for double click,
Single click event Always trigger - then - Second click triggers double click event but not single click event again.
Like first click on windows file explorer selects a folder, the double click opens it after selecting.

I think just removing the clickTriggered variable would achieve that from my code. (Need to check)

Thank you. Guys. I need to try it again myself. And see if I can come up with something.
There should be a way as every app has this functionality …

Maybe if make a counter. It will help? If single click counter ++ , if the time to second click less than 0.5 make counter ++
If click and counter = 1 - we got a single click
If click and counter = 2 - we got double click

On ButtonUp we make a single click function