How to control 2 seperate objects through touch

I am trying to write a script that you can rotate 2 objects by dragging your finger on screen. Seems simple enough, when rotating one object it works fine but when rotating both at the same time they start to stutter. I have tried using fingerId but I must be using it wrong. Below is the code I wrote any help would be great:

public float rotSpeed;
public Transform leftCube;
public Transform rightCube;

void Update()
{       
        foreach(Touch t in Input.touches)
        {
            if(t.position.x < Screen.width/2)
            {
                leftCube.Rotate(Vector3.up, -t.deltaPosition.x *  rotSpeed, Space.World);
            }
            else
            {
                rightCube.Rotate(Vector3.up, -t.deltaPosition.x * rotSpeed, Space.World);
            }
        }
}
public float rotSpeed;
public Transform leftCube;
public Transform rightCube;

public int leftId;
public int rightId;   
   
void Update()
{

       if(Input.touchCount > 0)
        {
           for(int i = 0; i < Input.touchCount; i++)
           {
               Touch t = Input.GetTouch(i);

               if(t.phase == TouchPhase.Began)
               {
                   if(t.position.x < Screen.width/2)
                   {
                       leftId = t.fingerId;
                   }
                   if(t.position.x > Screen.width/2)
                   {
                       rightId = t.fingerId;
                   }
               }

               if(t.phase == TouchPhase.Moved)
               {
                   if(t.fingerId == leftId)
                   {                       
                       leftCube.Rotate(Vector3.up, -t.deltaPosition.x * rotSpeed, Space.World);                       
                   }
                   
                   if(t.fingerId == rightId)
                   {
                       rightCube.Rotate(Vector3.up, -t.deltaPosition.x * rotSpeed, Space.World);  
                   }
               }         
           }
        }
}

You might need to do some smoothing on the inputs… what comes back from touch can be a bit noisy depending on the hardware. You would need to track the positions beyond each frame and use each new position to average it and smooth themotions. This would also require you to keep track of which position correlates to which smoothing variable.

Or perhaps did you perhaps put this script in twice?

Also, it’s extremely rare but your left/right test on lines 20 and 24 will fail if the touch is precisely at Screen.width / 2, so you might want to fix that. That is not what is causing your jitter however.

You might try categorizing the touches as left vs. right depending on whether they are currently in the left or right side of the screen, rather than whether they started there. (This might help if Unity makes any mistakes in tracking which finger is which. But it also might not help; I’m guessing.)

You should not be keeping track of your touches in any other way than by their touch id. Keep track of which side of the screen a touch started, and then track that touch via its touch id.

Correct me if I’m wrong but I thought the Touches array is not guaranteed to stay in the same order from frame to frame and that’s why Unity has https://docs.unity3d.com/ScriptReference/Touch-fingerId.html. Unless we’re talking about the same thing here…

2 Likes

Maybe only check the first two touches, see their position, and rotate whichever object accordingly. Additional touches will probably mess things up.

I was studying OP’s code and I think he is already doing that part okay. Lines 22 and 26 make note of the correct ID, and then lines 32 and 37 only act when that ID matches.

In fact the more I think about it, I’m guessing whatever device he’s on gets less stable when there are two fingers onscreen. A lot of lower-end Android devices are like this. Printing out the mouse delta data and then dropping it into a spreadsheet program to see how smooth it is would be one thing to try @MakeGames2020

2 Likes

Hi guys thanks for the responses.

-Smoothing is definitely something I will be implementing at a later stage but right now there is a clear difference when one finger is on the screen vs 2. So there is some issue somewhere.

-Am I using fingerId correctly? Both codes pasted above work but both give the same stuttering effect

-I am using a low end android device which I did think might cause an issue but I don’t think it should be this bad and I would like this to run on low end devices.

Had an idea. I am using the delta position of each touch to make the rotation. If I was to record the position of the touch for the left side and right side and calculate the delta manually it shouldn’t really matter about the fingerId or the potential touches array, not being the same each frame. All I would need to know is the position of whatever touch just so happens to be on that side of the screen, record that position, then get the position of whatever touch is on the same side of the screen the next frame and then calculate the delta that way.

Ok well below is the updated code. Still the same issues so I can only conclude that my phone sucks.

public float rotSpeed;
public Transform leftCube;
public Transform rightCube;

private Vector2 leftPosDelta;
private Vector2 rightPosDelta;

void Update()
{  

          
        foreach(Touch t in Input.touches)
        {
            if(t.position.x < Screen.width/2)
            {
                if(t.phase == TouchPhase.Began)
                {
                    leftPosDelta = t.position;
                }

                if(t.phase == TouchPhase.Moved)
                {
                    Vector2 d = t.position - leftPosDelta;
                    leftCube.Rotate(Vector3.up, -d.x * rotSpeed, Space.World);
                    leftPosDelta = t.position;
                }
            }
          
            if(t.position.x > Screen.width/2)          
            {
                if(t.phase == TouchPhase.Began)
                {
                    rightPosDelta = t.position;
                }
                if(t.phase == TouchPhase.Moved)
                {
                    Vector2 d = t.position - rightPosDelta;
                    rightCube.Rotate(Vector3.up, -d.x * rotSpeed, Space.World);
                    rightPosDelta = t.position;
                }
            }
        }
}

Well before you conclude, try this:

When there are two fingers, start accumulating their inputs to a string, one line at a time:

myString += finger1pos.x.ToString() + "," + finger2pos.x.ToString() + "\n";

That will make myString (member variable) grow unbounded.

After a few seconds (or when the length of that string is greater than 5000 bytes or so), send yourself an email with that data in the body:

https://answers.unity.com/questions/1581543/send-email-with-unity.html

When you get the data, throw it in a spreadsheet program and graph it. That will reveal how noisy it really is.

Obviously, make smooth movements with your fingers.

I actually downloaded these two apps:

Both of these give me the same stuttering effect when more than one finger is on the screen. So guess there is nothing I can do about it really. Kind of annoying that a phone would have this kind of issue would have thought that this would have been relatively simple for a phone to handle.

That’s unfortunate to hear. I’ve worked with some multitouch and it’s been relatively stable on my devices, but I guess it varies a lot. Try some other devices and see if things are different. Worst case, just have a caveat when you publish (if you’re going that route). So having a free version would be good to avoid any angry customers :wink:

1 Like

@MakeGames2020 just had one other thought: reboot your phone, if you don’t do that regularly. :slight_smile:

1 Like