How can I improve the responsiveness of my touch screen controls?

Here is a small clip of my game play: DisfiguredImpressionableGalapagossealion

The right side of the screen (finId2) controls the aiming and firing while the left side of the screen (finId1) is used to change the selected lane via swiping up and down.

As can be seen the gameplay depends on how fast the player can change lanes.

I have written a script that controls both sides of the screen but the swiping is a big sluggish and at times a swipe is missed entirely.

Is it because I am looping over all swipes way too often? Can anyone please have a look at my implementation of this and suggest how the swiping mechanism can be made more responsive?

    int screenDivision;
    int finId1 = -1;
    int finId2 = -1;
   
    bool tap, swipeUp, swipeDown;
    bool isDraging = false;
    Vector2 startTouch, swipeDelta;
    int swipeDeadzone = 5;
   
    void Start(){
   
            Input.multiTouchEnabled = true;
            screenDivision = Screen.width / 4;
            canAim = true;
           canFire = true;
       }
   
    void Update()
        {
            tap = swipeUp = swipeDown = false;
   
            //update the arrow pointer rotation (which is used for shooting the arrow in a straight line w.r.t. the tower)
   
            if (Input.touchCount > 0)
            {
                // loop through every touch
                foreach (var touch in Input.touches)
                {
                    if (touch.phase == TouchPhase.Began)
                    {
                        //For left half screen
                        if (touch.position.x <= screenDivision && finId1 == -1)
                        {
                            isDraging = true;
                            tap = true;
                            startTouch = touch.position;
                            finId1 = touch.fingerId;        //store the fingerId of the left touch for as long as touch has not been ended though TouchPhase.Ended
                        }
                        //For right half screen
                        else if (touch.position.x > screenDivision && finId2 == -1)
                        {
   
                            mouseStart = touch.position.y;
   
                            if (EventSystem.current.IsPointerOverGameObject(touch.fingerId))
                                canAim = false;
   
   
                            finId2 = touch.fingerId;
                        }
                    }
                    //touchPhase.Ended for the archer firing is handled in LateUpdate() so here only the left finger will be handled, target only the left finger via finId1 which was set in TouchPhase.Began
                    else if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
                    {
                        if (touch.fingerId == finId1)
                        {
                            //Reset or release the fingerId for next touch
                            finId1 = -1;
                            isDraging = false;
                            Reset();
                        }
                    }
   
                }
                //below if block if for the archer firing so only looking at fingerId2 here
                if (finId2 != -1)      //touch has begun and finId2 has been assigned  
                {
                    //if right tap is detected this block will set the animation state of the archer, play the bow sound and make ready to fire
                   
                }
               
   
            }
   
            //Below code handles the swiping mechanism of the left side of the screen.
            swipeDelta = Vector2.zero;
            if (isDraging)
            {
                foreach (var touch in Input.touches)
                {
                    //looping through all touches but only care about finId1 which is used for left half of screen
                    if (touch.fingerId == finId1)
                    {
                        swipeDelta = touch.position - startTouch;
                    }
                }
            }
   
            //Did we cross the deadZone?
            if (swipeDelta.magnitude > swipeDeadzone)
            {
                //which direction?
                float x = swipeDelta.x;
                float y = swipeDelta.y;
                if (Mathf.Abs(x) > Mathf.Abs(y))
                {
                    // Left or Right Swipe
                    //Unused in this game
                }
                else
                {
                    //up or down swipe
                    if (y < 0)
                    {
                        swipeDown = true;
                        spawner.Rotate(false);
                    }
                    else
                    {
                        swipeUp = true;
                        spawner.Rotate(true);
                    }
                }
   
                Reset();
            }
   
        }

The swiping mechanism is handled entirely in the Update() block. Where as the final state of the arrow firing is handled in the LateUpdate() as done below:

    void LateUpdate()
    {
        //if the player can aim
        if (Input.touchCount > 0)
        {
            if (canAim)
            {
                foreach (var touch in Input.touches)
                {
                    if (touch.fingerId == finId2)
                    {
                        if (touch.phase == TouchPhase.Moved)
                        {
                            //code to move the line renderer showing arrow line prediction.
   
   
                        }
                        else if (touch.phase == TouchPhase.Ended)
                        {
                            zRotation = 0;
                        }
   
                    }
                }
            }
   
            foreach (var touch in Input.touches)
            {
                if (touch.fingerId == finId2)
                {
                    if (touch.phase == TouchPhase.Ended)
                    {
                        finId2 = -1;
                       
                       // code that handles arrow behaviour and shoots arrow
   
                        //can aim again
                        canAim = true;
                    }
                }
            }
   
        }
    }
   
   
    private void Reset()
    {
        startTouch = swipeDelta = Vector2.zero;
        isDraging = false;
    }

I know this might not be the most elegant way to achieve what I want but, it is what I could put together from reading online documentation for multitouch.

Any guidance on how to improve this would be greatly appreciated.

Check your framerate.

On iOS, you have to explicitly set Application.targetFramerate = 60; and disable VSync. Then, do everything inside an Update (don’t do anything inside LateUpdate). Finally, your swipeDeadzone might be too large.

1 Like