Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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
0
Question by rickyuli44 · May 05, 2020 at 01:24 PM · raycastunity 2ddrag-and-dropmultitouch

Drag multiple object using multitouch?

Hi guys, I have a problem when dragging several objects at the same time in 2D using multitouch. I need to colliding 2 object or more if they have same tag and if they aren't, the dragged object will return to its original position. Count and phase is working, but still cant drag any object. Please help, stuck for 1 week. T_T

void Update() {

     if (Input.touchCount > 0)
     {
         foreach (Touch t in Input.touches)
         {
             touches[t.fingerId] = Camera.main.ScreenToWorldPoint(Input.GetTouch(t.fingerId).position);
             Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(t.fingerId).position);
             RaycastHit hit;
             if (Physics.Raycast(ray, out hit))
             {
                 if (hit.transform.tag == "Draggable")
                 {
                     if (Input.GetTouch(t.fingerId).phase == TouchPhase.Began)
                     {
                         startPos = hit.transform.position;
                     }
                     if (Input.GetTouch(t.fingerId).phase == TouchPhase.Moved)
                     {
                         hit.transform.position = Input.GetTouch(t.fingerId).position;
                     }
                     if (Input.GetTouch(t.fingerId).phase == TouchPhase.Ended)
                     {
                         hit.transform.position = startPos;
                     }
                 }
             }
         }
     }

,

Comment
Add comment
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

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by Bunny83 · May 05, 2020 at 03:40 PM

You are confusing things here a bit. Input.GetTouch takes an index not a fingerID. There is no direct way to query a touch for a certain fingerID. You usually just iterate through all touches and use the fingerID of the current touch in your logic.


Note that the fingerID does not change over the time as long as a touch is still tracked, So just imagine putting 5 fingers down one after another. So you will have 5 touches in your touches array (touchcount ==5). The fingerIDs would probably be also something like the numbers from 0 to 4 but they do not correspond to the index. If you now release the first 3 fingers and keep the last to the touch count goes down to 2 and the only valid indices for GetTouch are 0 and 1. However the fingerIDs of those touches are most likely 3 and 4 since, as I said, the fingerID doesn't change as long as the touch is still tracked.


Your next issue might be your startPos variable. You only have a single startPos variable. If you want to be able to drag multiple objects at the same time you have to track this information for each object you're dragging. Also it usually makes more sense to store the object you drag around along with the corresponding fingerID and startpos in a custom class / struct.


The next issue is you set the dragged objects position to the hit position. However since the hit position is on the surface of the collider of your object the object most likely would move towards the camera until it wents through the near clipping plane, You should seperate the actual picking of the object (TouchPhase.Began) from the actual dragging (TouchPhase.Moved). Touch movement on a 2d screen is of course just a 2d motion. So to translate that properly into 3d there are generally two ways:

  • Either calculate the distance of the object from the camera when you start dragging and place the object simply at that distance along the Ray (Ray.GetPoint(dist)). That way you would drag your object on a spherical surface around your camera origin since we will always have this distance from the camera. So when the touch point moves we describe an angle in worldspace

  • The second more common solution is to use a "drag plane" which we place at the oritinal objects position and use that to determine the actual position where the object should be placed.

Something like this:

 public class DragObject
 {
     public Transform obj;
     public int fingerID;
     public Vector3 dragOffset;
     public Vector3 startPos;
     public Plane dragPlane;
 }
 public Dictionary<int, DragObject> draggedObjects = new Dictionary<int, DragObject>();
 private void Update()
 {
     foreach (Touch t in Input.touches)
     {
         Ray ray = Camera.main.ScreenPointToRay(t.position);
         if (t.phase == TouchPhase.Began)
         {
             RaycastHit hit;
             if (Physics.Raycast(ray, out hit) && hit.transform.CompareTag("Draggable"))
             {
                 DragObject dragO;
                 if (!draggedObjects.TryGetValue(t.fingerId, out dragO))
                 {
                     dragO = new DragObject();
                     draggedObjects.Add(dragO.fingerID, dragO);
                 }
                 dragO.fingerID = t.fingerId;
                 dragO.obj = hit.transform;
                 dragO.startPos = hit.transform.position;
                 dragO.dragPlane = new Plane(-Camera.main.transform.forward, dragO.startPos);

                 float dist;
                 dragO.dragPlane.Raycast(ray, out dist);
                 dragO.dragOffset = dragO.startPos - ray.GetPoint(dist);
             }
         }
         else if (t.phase == TouchPhase.Moved)
         {
             DragObject dragO;
             if (draggedObjects.TryGetValue(t.fingerId, out dragO))
             {
                 if (dragO.obj == null)
                 {
                     // object has been destroyed, so remove this DragObject and continue
                     draggedObjects.Remove(t.fingerId);
                     continue;
                 }
                 float dist;
                 dragO.dragPlane.Raycast(ray, out dist);
                 dragO.obj.position = ray.GetPoint(dist) + dragO.dragOffset;
             }
         }
         else if (t.phase == TouchPhase.Ended || t.phase == TouchPhase.Canceled)
         {
             DragObject dragO;
             if (draggedObjects.TryGetValue(t.fingerId, out dragO))
             {
                 if (dragO.obj == null)
                 {
                     dragO.obj.position = dragO.startPos;
                 }
                 draggedObjects.Remove(t.fingerId);
             }
         }
     }
 }


Some notes:
When you touch with a finger it casts a ray against the objects in the scene to determine which object you hit. If the object we hit can be dragged we create / update the DragObject instance for the current fingerID. We of course save the actual object reference of the object we've hit (obj) but also the fingerID and the startpos of this object. In addition we setup a plane perpendicular to the camera plane which we will use to drag the object around. We also calculate the drag offset since we most likely did not touch the object at its origin. This offset will be used when we update the objects position.


Whenever a finger is moved we check our dictionary if the fingerID actually has a DragObject. If we have we simply update the objects position according to the hit point on the drag plane + our drag offset


When the touch finishes (either "Ended" or "Cancelled") we do move the object back to the initial start position of this object and also remove the object from our dictionary since the touch no longer exists from now on.


That's all what is happening here. Of course at the moment the object will always return back to the starting point once you release the object. If you don't want that you have to remove the line

 dragO.obj.position = dragO.startPos;

from the last case.

Comment
Add comment · Show 1 · 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
avatar image rickyuli44 · May 06, 2020 at 01:21 PM 0
Share

Thanks for your answer. The phase moved is moving correctly but cant still do mul$$anonymous$$ch, and when the phase equals to ended the object position always flickering to 0. With your logic I tried to code in short way. In this case, the object will stay when the phase ended (only moving). I can move 8 objects Anyway I cant run your code in several device, why is it? And also $$anonymous$$e cant run in several device too, why is it?

if(Input.touchCount > 0) { for (int i = 0; i <= Input.touchCount; i++) { Touch touch = Input.GetTouch(i); Vector2 worldPoint = Camera.main.ScreenToWorldPoint(touch.position); RaycastHit2D hit = Physics2D.Raycast(worldPoint, Vector2.zero);

             if (Input.GetTouch(i).phase == TouchPhase.Began)
             {
                startPos[i] = hit.transform.position;
                 //startPos[i] = worldPoint;
             }
             if (Input.GetTouch(i).phase == TouchPhase.$$anonymous$$oved)
             {
                 hit.transform.position = worldPoint;
             }
             if (Input.GetTouch(i).phase == TouchPhase.Ended)
             {
                 hit.transform.position = startPos[i];
             }
         }
     }

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

180 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image 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

Drag object and position(snap) on another similar one using Raycasting? 0 Answers

Make a event trigger raycast ignore a layer 1 Answer

why gameobject / raycast when dragged is not accurately following the touch position in unity 0 Answers

script problem even though i have no errors 2 Answers

Raycast2D not returning any transform instead keeps returning void. 1 Answer


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