FernandoRosa
FernandoRosa

Reputation: 101

Is Unit and Android unable to precisely follow a finger?

I'm creating a Android game with Unity and I'm trying to make an object to follow my finger. This is the code I'm using.

for (int i = 0; i < Input.touchCount; i++)
    {
        RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.touches[i].position), Vector2.zero);

        Vector3 touchPosition = Camera.main.ScreenToWorldPoint(Input.touches[i].position);

        if (Input.GetTouch(i).phase == TouchPhase.Moved && hit.collider != null)
        {
            transform.position = new Vector2(touchPosition.x, touchPosition.y + sizeY);
        }
    }

I put the collider bellow the object and I added the size of the object to the Y, so it appears above my finger. The problem is that if I move my finger slightly faster, I lose the object, that stays behind. Since the object lags behind, if I move my finger faster I end up out of the collider area and the object just stop moving. The only way I found that works is to get rid of the Raycast thing and make the object follow the touch anywhere in the screen (I don't like that).

I just want to know if this is the best I can get from Unity and Android or if there a is way to make an object follow the finger in a one-by-one movement, with precision, without lag. I'm testing on a Samsung Galaxy S8 just with the object and nothing else.

Upvotes: 1

Views: 1446

Answers (1)

Programmer
Programmer

Reputation: 125365

You are not alone with this issue. Unity's Input API is frame-rate based and may not keep with the speed of the touch movement on the screen. If you're working on something that requires fast response based on the touch on the screen, use the new Unity's InputSystem. This API is still in experimental mode.

Its Touchscreen class can be used to access the touch on the screen. Your current code should translate into something like below:

public int touchIndex = 0;

void Update()
{
    Touchscreen touchscreen = UnityEngine.Experimental.Input.Touchscreen.current;

    if (touchscreen.allTouchControls[touchIndex].ReadValue().phase != PointerPhase.None &&
               touchscreen.allTouchControls[touchIndex].ReadValue().phase == PointerPhase.Moved)
    {
        Vector2 touchLocation = touchscreen.allTouchControls[touchIndex].ReadValue().position;   
        RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(touchLocation), Vector2.zero);    
        Vector3 touchPosition = Camera.main.ScreenToWorldPoint(touchLocation);
        transform.position = new Vector2(touchPosition.x, touchPosition.y + sizeY);   
    }
}

Upvotes: 1

Related Questions