Search code examples
c#unity-game-enginetimer

Unity3D: Timer created at TouchEnded not working


Using Unity3d 2018.2.1 and C#

Problem: StartTimer not starting when user clicks screen, touch not being registered so timer never starts.

In FixedUpdate() im looking at when the user touches the screen to start a timer. If the user hasn't touched the screen again and it has been 15 seconds then do something. If the user touches the screen before the 15 seconds, then restart the timer.

public float uiStartTime = 0f;
public float uiCurrentTime = 0f;
public float uiMaxTime = 15f;

private void FixedUpdate()
{
    if (Input.touchCount > 0)
    {
        Touch touch = Input.GetTouch(0);

        if (touch.phase == TouchPhase.Ended)
        {
            uiStartTime = Time.time;
        }
    }

    uiCurrentTime = Time.time;

    if (uiStartTime - uiCurrentTime == uiMaxTime)
    {
        //  Reset Timer
        uiStartTime = 0f;
        uiCurrentTime = 0f;

        // Do Something
    }
}

Solution

  • Problem: StartTimer not starting when user clicks screen, touch not being registered so timer never starts.Im using a mouse to test but will deploy for mobile

    That's the main issue here. Of-course you still have some logical error in your code but timer shouldn't start since you're using mouse to test the Input.touchCount and Input.GetTouch API. These two API only work on the mobile device since they use touch instead of mouse.

    If you want to use them in the Editor, use Unity Remote 5. Download it, on your mobile device, enable it in the Editor by going to Edit->Project Settings->Editor then connect your device to your computer. You should be able to use the touch API in your Editor without having to build it. See this post for more information about Unity Remote 5.


    If you want the code to be more compatible with both mouse and touch then make a simple function that wraps around the touch and mouse API. You can then use the combination of UNITY_STANDALONE and UNITY_EDITOR preprocessor directives to detect when you are not running on a mobile platform.

    Here is a simple mobile/desktop touch wrapper that works without Unity Remote 5:

    bool ScreenTouched(out TouchPhase touchPhase)
    {
        #if UNITY_STANDALONE || UNITY_EDITOR
        //DESKTOP COMPUTERS
        if (Input.GetMouseButtonDown(0))
        {
            touchPhase = TouchPhase.Began;
            return true;
        }
    
        if (Input.GetMouseButtonUp(0))
        {
            touchPhase = TouchPhase.Ended;
            return true;
        }
        touchPhase = TouchPhase.Canceled;
        return false;
        #else
    
        //MOBILE DEVICES
        if (Input.touchCount > 0)
        {
            touchPhase = Input.GetTouch(0).phase;
            return true;
        }
        touchPhase = TouchPhase.Canceled;
        return false;
        #endif
    }
    

    Below is how to use it to get what you want in your question:

    public float uiStartTime = 0;
    public float uiMaxTime = 15f;
    private bool timerRunning = false;
    
    private void Update()
    {
        //Increment timer if it's running
        if (timerRunning)
            uiStartTime += Time.deltaTime;
    
        TouchPhase touchPhase;
    
        if (ScreenTouched(out touchPhase))
        {
            //Check for keypres and start timer if it's not running
            if (touchPhase == TouchPhase.Ended && !timerRunning)
            {
                timerRunning = true;
            }
    
            //If the user touches the screen before the 15 seconds, then restart the timer.
            else if (touchPhase == TouchPhase.Ended && timerRunning && uiStartTime < uiMaxTime)
            {
                uiStartTime = 0f;
                Debug.Log("Timer Reset");
            }
        }
    
        //If the user hasn't touched the screen again and it has been 15 seconds then do something.
        if (uiStartTime >= uiMaxTime)
        {
            // Do Something
            Debug.Log("Timer not touched for 15 seconds");
        }
    }