WokerHead
WokerHead

Reputation: 967

Unity3D: C# - Can't seem to handle single/double/ hold touches correctly

Using Unity3D 2018.2

Trying to get Single tap, Double tap, and Hold tap.

Problems having:

Single Tap: Sometimes won't register my single tap

Double Tap: Gets called 8 times every time I double Tap my device

Triple Tap: Double Tap gets called 10 times then Triple gets called 9 times

Here is my code, please your help would be appreciated on such a simple task I can not get right, new to C# and Unity

private void handleTouchTypes()
{
    foreach (Touch touch in Input.touches)
    {

        float tapBeginTime = 0;
        float tapEndedTime = 0;

        //  Touches Began
        if (touch.phase == TouchPhase.Began)
        {
            tapBeginTime = Time.time;
        }

        //  Touches Ended
        if (touch.phase == TouchPhase.Ended)
        {
            tapEndedTime = Time.time;

            //  Single Touch: for 0.022f of a Second
            if (touch.tapCount == 1 && ((tapEndedTime - tapBeginTime) < 0.03f))
            {
                Debug.Log("Single Touch");
            }

            //  Hold Touch: within half a second .5f to 1f
            if (touch.phase == TouchPhase.Moved && touch.deltaPosition.magnitude < 0.02f && (tapEndedTime - tapBeginTime) >= 0.5f && (tapEndedTime - tapBeginTime) <= 1f)
            {
                Debug.Log("Holding Touch");
            }
        }

        if (touch.tapCount == 2)
        {
            //  Double Tap
            Debug.Log("Double Tap");
        }
        if (touch.tapCount >= 3)
        {
            //  Triple Tap
            Debug.Log("3 Touches and/or more");
        }
    }
}

Upvotes: 0

Views: 777

Answers (1)

andeart
andeart

Reputation: 951

There's a few different things amiss here.

1) You're calling

    float tapBeginTime = 0;
    float tapEndedTime = 0;

at the start of each Touch element. Meaning your check for

(tapEndedTime - tapBeginTime) < 0.03f

will never pass, because tapBeginTime will have been reset to 0 by the point you set tapEndedTime = Time.time;.

If you want to track these times on a per-touch basis, I'd suggest creating a dictionary that maps the touches' fingerIds to their starting times. You don't need to record the tapEndedTime per touch, as it should suffice as a local variable calculated as needed.

2) I'm not a 100% sure on this, but you may also need to check if (touch.phase == TouchPhase.Ended) in addition to the if (touch.tapCount == 2) check, for accurate results. I know I've personally had issues not explicitly checking so in the past.

3) You're also doing a if (touch.phase == TouchPhase.Moved) check inside an if (touch.phase == TouchPhase.Ended) block. I'll let you figure this one out :)

I hope these points help you figure some of the immediate issues out. Once you've solved these surface issues, I suggest you explore ways to optimise your resulting code even further. Good luck!

Upvotes: 1

Related Questions