Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by synergies · Dec 11, 2012 at 10:06 PM · movementaccelerationmultitouch

Multitouch: Second touch interferes with the first.

I am trying to create a control system for touch devices. Touching the left side of the screen moves the cameras position and the right side of the screen moves the camera angle (much like fps controls). The problem comes with multitouch. For some reason, the moment I touch my second finger, it overwrites the first fingers origin.

Here is the current code in c#

 private Rect leftBox = new Rect(0, 0, Screen.width / 2, Screen.height);
 private Vector2 leftOrigin = new Vector2();
 private Vector2 rightOrigin = new Vector2();
 private float dragSpeed = 2;
 private string side = "left";
 
   private void touchMovementManager()
     {
         if (Input.touchCount > 0)
         {
             foreach (Touch touch in Input.touches)
             {
                 if (touch.phase == TouchPhase.Began)
                 {
                     // add origin for this touch to array
                     if (leftBox.Contains(touch.position))
                     {
                         leftOrigin = touch.position;
                         side = "left";
                     }
                     else
                     {
                         rightOrigin = touch.position;
                         side = "right";
                     }
                 }
 
                 if (touch.phase != TouchPhase.Ended && touch.phase != TouchPhase.Canceled)
                 {
                     switch (side)
                     {
                         case "left":
                             Vector3 pos = Camera.main.ScreenToViewportPoint(touch.position - leftOrigin);
                             Vector3 move = Camera.main.transform.TransformDirection(pos);
                             Vector3 newMove = new Vector3(move.x, -move.z, move.y);
                             transform.Translate(newMove, Space.World);
                             break;
                         case "right":
                             Camera.mainCamera.transform.Rotate(Vector3.up * (touch.position.x - rightOrigin.x) / (dragSpeed * 100));
                             Camera.mainCamera.transform.Rotate(Vector3.left * (touch.position.y - rightOrigin.y) / (dragSpeed * 100));
                             break;
                         default:
                             break;
                     }
                 }
             }
         }
     }

So I'll try explain as best I can as what is meant to be happening. For every touch, if the touch has just began, it stores the origin (depending on if its the left side of the screen or right side). On the next frame, it then alters movement by acceleration based on how far the finger has moved from the origin.

Heres where it breaks: When a second finger is added to the other side of the screen, it changes the movement to whatever side the second finger has touched but it accelerates rapidly as the first finger is far away from the origin.

What I am confused about is that because the entire statement is wrapped in a foreach, it should be executing this seperately for each touch (finger), but for some reason they are getting muddled.

Be aware that touchMovementManager() is called on the Update() loop.

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image richard3d · Dec 11, 2012 at 11:29 PM 0
Share

I had this exact same problem. http://answers.unity3d.com/questions/257505/touchdeltaposition-works-differently-with-two-fing.html

Now unfortunately I have not found a good answer, however in my research there are a few things to consider. How your device implements touch specifically multi touch can make a big difference (this is an inherent issue with android devices, haven't messed with iOS as much). The second is that the touch index/ID and the data for the touch itself are not necessarily correlated. $$anonymous$$eaning the first iteration of your loop will not always correspond to data from the same finger. (This drove me insane!) I dont know if Unity 4 has fixed or addressed this but in 3.5 it was killing me, especially when trying to implement my own pinch zoom. You can make it work if you are willing to implement some filtering and also infer which finger is touching based on last movements etc. but it is work.

avatar image synergies · Dec 13, 2012 at 12:37 AM 0
Share

Hey guys, got it all working perfectly with how I wanted it. I'm going to upload the code here for learning purposes. I'm not happy with the code itself, its something I hacked in very quickly (especially the rotation stuff), but I found very little documentation for what I expect should be quite a popular control system. Thanks to Bunny who helped me sort out the fingerID stuff.

The code:

http://pastie.org/private/eb6i0e7isnk4xkwlz9ra

Should work if you add it to the main camera along with a prefab.

Controls:

Swipe the left side of the screen to move the position. Swipe the right side of the screen to change the rotation. Tap on a cube to trigger a raycast(I was experimenting with being able to interact with objects while using this movement system).

1 Reply

· Add your reply
  • Sort: 
avatar image
2

Answer by Bunny83 · Dec 12, 2012 at 01:07 AM

Your "side" variable does exist only once. Each touch can and will set it and overrides the value the first touch has set.

You should use two variables and not a boolean but an int!

Each Touch has a fingerId this fingerId doesn't change until the touch is ended. This id is the only thing which you can use to identify a certain finger. So you have a move finger and a rotate finger, you need a variable for each one. Now when a touch happens in the "move area" you set the moveFingerID to touch.fingerId. When a touch happens in the "rotate area" You set the rotateFingerID to touch.fingerId.

Now you can identify each finger and assign each to the right actions.

In addition you should "clear" the fingerId when it's touch ended / canceled.

Something like that:

 private Rect leftBox = new Rect(0, 0, Screen.width / 2, Screen.height);
 private Vector2 positionRef = new Vector2();
 private int positionFingerId = -1;
 private Vector2 rotationRef = new Vector2();
 private int rotationFingerId = -1;
 private float dragSpeed = 2;
 
 private void touchMovementManager()
 {
     foreach (Touch touch in Input.touches)
     {
         if (touch.phase == TouchPhase.Began)
         {
             // add origin for this touch to array
             if (leftBox.Contains(touch.position))
             {
                 positionRef = touch.position;
                 positionFingerId = touch.fingerId;
             }
             else
             {
                 rotationRef = touch.position;
                 rotationFingerId = touch.fingerId;
             }
         }

         if (touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled)
         {
             if (touch.fingerId == positionFingerId)
                 positionFingerId = -1;
             if (touch.fingerId == rotationFingerId)
                 rotationFingerId = -1;
         }
         else
         {
             if (touch.fingerId == positionFingerId)
             {
                 Vector3 pos = Camera.main.ScreenToViewportPoint(touch.position - positionRef);
                 Vector3 move = Camera.main.transform.TransformDirection(pos);
                 Vector3 newMove = new Vector3(move.x, -move.z, move.y);
                 transform.Translate(newMove, Space.World);
             }
             if (touch.fingerId == rotationFingerId)
             {
                 Camera.mainCamera.transform.Rotate(Vector3.up * (touch.position.x - rotationRef.x) / (dragSpeed * 100));
                 Camera.mainCamera.transform.Rotate(Vector3.left * (touch.position.y - rotationRef.y) / (dragSpeed * 100));
             }
         }
     }
 }

ps, i changed your script here in the editor, so no guarantee that it compiles right away :D I renamed your left and right variables since you should use names which are bound to their function. I would also rename the "leftBox" and probably create another one for the rotation. If you decide to flip the controls (or if you make it configurable for the user) the "left" is very confusing.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

12 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

moving in a straight line, but variable speed 1 Answer

How do I create a rubber band effect on a camera forward movement? 1 Answer

Disable movement control during jump 3 Answers

How to move player by accelerometer 0 Answers

Moving left and right touch problem 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges