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 /
This question was closed Dec 22, 2015 at 01:43 PM by Ronin Davis for the following reason:

The question is answered, right answer was accepted

avatar image
0
Question by Ronin Davis · Dec 22, 2015 at 12:13 PM · rigidbodyrigidbody2dphysics2ddragmouseposition

Drag Object Script Problem

So i was making a script that would allow me to click and drag a rigidbody with the mouse, and for the most part it was working, but a minute problem i had with it was that that when i clicked on it the object snapped to my cursor, because in the script it just goes to the mouse position, but i wanted it to drag it around by the point on the object it clicked. I was hoping somebody could help by telling me how i could do that. Feel free to ask about anything you don't understand. Thank You.

My script:

 public class Drag : MonoBehaviour {
     float d;
 
     public Rigidbody2D rigid;
 
     public bool held;
 
     void Update (){
         d = Input.GetAxis("Mouse ScrollWheel");
         if(held == true && d > 0f){
             transform.Rotate(Vector3.forward * d * 7);
         }else if(held == true && d < 0f){
             transform.Rotate(Vector3.forward / d / 7);
         }
     }
 
     void OnMouseDrag (){
         Vector2 mousePosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
         Vector2 objPosition = Camera.main.ScreenToWorldPoint(mousePosition);
 
         transform.position = objPosition;
         rigid.constraints = RigidbodyConstraints2D.FreezePositionX | RigidbodyConstraints2D.FreezePositionY;
         held = true;
     }
 
     void OnMouseUp(){
         rigid.constraints = RigidbodyConstraints2D.None;
     }
 }
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

2 Replies

  • Sort: 
avatar image
0
Best Answer

Answer by wibble82 · Dec 22, 2015 at 01:00 PM

Probably the simplest way to achieve something along these lines would be:

  • When the mouse is first clicked, calculate a 3D position the user clicked on in world space (presumably at z=0, as that's what you're current assuming here by converting ScreenToWorldPoint to a 2D vector

  • Use transform.InverseTransformPoint to get the 'local space' position that corresponds to, and store it

  • Each frame while dragging, convert the stored 'local space' position back to world space using transform.TransformPoint

  • Calculate the difference between the current mouse position and that new position

  • Add the difference to transform.position

What we're effectively doing with that process is storing 'where on the object' the user originally clicked. Then each frame we're taking that point on the object, and working out 'where it is now'. Finally, we're comparing that position to the current mouse position and working out the error, which we're correcting by changing the position of the object.

Very roughly, it'd look like this:

         public class Drag : MonoBehaviour 
         {
             float d;
  
             public Rigidbody2D rigid;
  
             public bool held;           //stores whether currently holding the object
             Vector3 localHeldPosition;  //stores where we grabbed it
  
             void Update ()
             {
                 d = Input.GetAxis("Mouse ScrollWheel");
                 if(held == true && d > 0f){
                     transform.Rotate(Vector3.forward * d * 7);
                 }else if(held == true && d < 0f){
                     transform.Rotate(Vector3.forward / d / 7);
                 }
             }
  
             void OnMouseDrag ()
             {
                 //get mouse position
                 Vector2 screenMousePosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
 
                 //convert to world space (on z=0 plane)
                 Vector3 worldMousePosition = Camera.main.ScreenToWorldPoint(screenMousePosition);
                 worldMousePosition.z = 0; //this is to make sure the position stays on the z=0 plane
 
                 //if weren't holding last frame, remember where we grabbed it in local space
                 if(!held)
                 {
                     localHeldPosition = transform.InverseTransformPoint(worldMousePosition);
                     held = true;
                 }
 
                 //calculate the current position of the grabbed point in world space
                 Vector3 worldHeldPosition = transform.TransformPoint(localHeldPosition);
 
                 //calculate the 'error' - i.e. how much we need to move that point to fix things
                 Vector3 worldDelta = worldMousePosition-worldHeldPosition;
                  
                 //fix it just by moving out object
                 transform.position += worldDelta;
                 rigid.constraints = RigidbodyConstraints2D.FreezePositionX | RigidbodyConstraints2D.FreezePositionY;
                 held = true;
             }
  
             void OnMouseUp()
             {
                 rigid.constraints = RigidbodyConstraints2D.None;
                 held = false;
             }
         }

But there's definitely work to do:

  • I'm not sure how your scene is setup, but unless you're using an orthographc camera and all your objects are on the z=0 plain, there's likely to be issues with conversion from screen to world space

  • Moving rigid bodies by directly setting the transform.position isn't good - you should look into how to correctly move rigid bodies around (look up MovePosition)

  • This will move the object, but won't give an actual 'drag' effect - the object won't rotate towards the cursor. If you want that behaviour you'll need to look into point forces.

Hope that helps get you started :)

-Chris

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 Ronin Davis · Dec 22, 2015 at 01:13 PM 0
Share

Thank you so much this works great.

To clarify how my scene is currently working, i am using orthographic camera because my prototype thing is 2D, i basically just want to make some 2D physics environment for fun :D.

I will look into a better way of moving my object around, i just started on this today so i wanted to get some sort of fun mechanic working to keep me interested.

Thank You. :D

avatar image
0

Answer by Ronin Davis · Dec 22, 2015 at 02:14 PM

I figured out the best way to move the object for anyone who stumbles upon this thread wondering how to do this.

So here's the script i ended up with:

    float d;
 
     public Rigidbody2D rigid;
 
     public bool held;           //stores whether currently holding the object
     Vector3 localHeldPosition;  //stores where we grabbed it
 
     void Update ()
     {
         d = Input.GetAxis("Mouse ScrollWheel");
         if(held == true && d > 0f){
             transform.Rotate(Vector3.forward * d * 7);
         }else if(held == true && d < 0f){
             transform.Rotate(Vector3.forward / d / 7);
         }
     }
 
     void OnMouseDrag ()
     {
         //get mouse position
         Vector2 screenMousePosition = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
 
         //convert to world space (on z=0 plane)
         Vector3 worldMousePosition = Camera.main.ScreenToWorldPoint(screenMousePosition);
         worldMousePosition.z = 0; //this is to make sure the position stays on the z=0 plane
 
         //if weren't holding last frame, remember where we grabbed it in local space
         if(!held)
         {
             localHeldPosition = transform.InverseTransformPoint(worldMousePosition);
             held = true;
         }
 
         //calculate the current position of the grabbed point in world space
         Vector3 worldHeldPosition = transform.TransformPoint(localHeldPosition);
 
         //calculate the 'error' - i.e. how much we need to move that point to fix things
         Vector3 worldDelta = worldMousePosition-worldHeldPosition;
 
         //fix it just by moving out object
         rigid.MovePosition(transform.position + worldDelta);
         held = true;
     }
 
     void OnMouseUp()
     {
         rigid.constraints = RigidbodyConstraints2D.None;
         held = false;
     }
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

Follow this Question

Answers Answers and Comments

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Recalculating collisions after Physics2D.IgnoreLayerCollision()? 1 Answer

Is it possible to disable collisions for separate physics scene? 0 Answers

Slow a rigidbody to a stop over a set distance? 1 Answer

Move Rigidbody2d along with parent object 1 Answer

How to make physics relative to moving parent 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