Search code examples
c#unity-game-enginetimersensorstouches

Detect long touch in Unity 3D


I'm trying to detect long touch on the screen by using Time.time or Time.deltatime, but nothing works. It should turn out like this: after beginning TouchPhase.Stationary (or Began) timer should goes on, then after TouchPhase.Ended timer can be reset to 0. But here is condition that checks, if I held the button on the sensor less than 0.5 sec - do something.

Problems:

  1. Time.Deltatime for some reason it does not add up to a variable for each iteration, but constantly assigns a new value equal to the time of the last frame, somewhere around 0.02-0.1

  2. Time.time constantly adds a value to the variable, when subtracting the time of pressing the screen and the vacation time, the variable that should be reset to zero, but with each iteration of actions, the value for some reason cannot vary from 0.0 - 0.05, the timer for some reason constantly sums up the value and the variable constantly increases

My ask: how can I track how many seconds my finger was on the screen?

void TapOrLongTounch()
{
    float pressTime = 0;
    float endPressTime = 0;
    if (Input.touchCount > 0)
    {
        Touch touch = Input.GetTouch(0);
        if (touch.phase == TouchPhase.Stationary)
        {
            pressTime += Time.time;
        }

        if (touch.phase == TouchPhase.Ended)
        {
            endPressTime = Time.time - pressTime;

            if (endPressTime < 0.5f)
            {
                //Do something;
            }
            endPressTime = 0;
        }
    }
}

Solution

  • First of all Time.time is

    This is the time in seconds since the start of the application [...].

    What you are doing is basically exponentially adding more and more time every frame.

    → What you rather want to count is the Time.deltaTime

    The interval in seconds from the last frame to the current one [...].

    like

    if (touch.phase == TouchPhase.Stationary)
    {
        pressTime += Time.deltaTime;
    }
    

    so that pressTime results in the total amount of time in seconds the touch was stationary.

    BUT you also have it as a method variable so it continuously starts from 0 anyway!

    → You rather want to have a class field for it!


    Then further the

    if (touch.phase == TouchPhase.Ended)
    {
        endPressTime = Time.time - pressTime;
        ...
        
    

    makes no sense / is pretty redundant. The pressTime already is the total time in seconds the touch was stationary!


    In general I would rather use a switch-case and do e.g.

    float pressTime = 0;
    
    void TapOrLongTounch()
    {
        if (Input.touchCount <= 0) return;
        
        var touch = Input.GetTouch(0);
    
        switch(touch.phase)
        {
            // Maybe you also want to reset when the touch was moved?
            //case TouchPhase.Moved:
            case TouchPhase.Began:
                pressTime = 0;
                break;
    
            case TouchPhase.Stationary:
                pressTime += Time.deltaTime;
                break;
    
            case TouchPhase.Ended:
            case TouchPhase.Canceled:
                if (pressTime < 0.5f)
                {
                    //Do something;
                }
                pressTime = 0;
                break;
        }
    }