Search Unity

Trouble Making An Object Follow Mouse

Discussion in '2D' started by Valente11, May 21, 2014.

  1. Valente11

    Valente11

    Joined:
    Sep 20, 2013
    Posts:
    12
    Hi there,

    I'm having some serious problems having my player object rotate toward the mouse direction (on mouse click) and travel along its transform.right axis. Similar to how a car is always traveling forward, only its forward is constantly pointing different ways - you get the picture. Before you click away, yes I've done extensive searches for a solution and have been unsuccessful. I can't identify the problem. I'm completely nonplussed! I'm here, I have my code, and I even drew you some pictures and everything.

    Here's a picture to illustrate my point. Please excuse my bad handwriting.

    What I would like to happen: The player character is always moving along its own right axis. When the player clicks (or holds) the mouse, the player character rotates toward the click (while still moving). The goal is to have a sort of arc happen while it turns. Like this:
    http://imgur.com/9Wl2qW1


    Here is the commented code that should make such a thing happen.
    Code (csharp):
    1.  
    2. public float moveSpeed;             // movement speed
    3.     public float turnSpeed;         // rotation speed
    4.  
    5.     private Vector3 moveDir;        // desired rotation
    6.  
    7.  
    8.     void Start ()
    9.     {
    10.     }
    11.    
    12.  
    13.     void Update ()
    14.     {
    15.  
    16.         // store current position each frame
    17.         Vector3 curPos = transform.position;   
    18.  
    19.         // while mouse is clicked
    20.         if (Input.GetButton ("Fire1"))
    21.         {
    22.             // store mouse position
    23.             Vector3 mousePos = Camera.main.ScreenToWorldPoint (Input.mousePosition);
    24.  
    25.             // get a direction vector, assign to moveDir
    26.             moveDir = mousePos - curPos;
    27.             // make sure there is no movement along z
    28.             moveDir.z = 0;
    29.             // normalize direction vector
    30.             moveDir.Normalize();
    31.         }
    32.  
    33.         // Get angle of direction vector. Convert to degrees
    34.         float targetAngle = Mathf.Atan2 (moveDir.y, moveDir.x) * Mathf.Rad2Deg;
    35.         // rotate player from current rot to targetAngle (as Euler)
    36.         transform.rotation =
    37.             Quaternion.Slerp (transform.rotation,
    38.                               Quaternion.Euler (0,0,targetAngle),
    39.                               turnSpeed * Time.deltaTime);
    40.  
    41.  
    42.         // move player along its positive x axis by speed.
    43.         transform.Translate (transform.right * moveSpeed * Time.deltaTime);
    44.     }
    It's not working.

    Here's what's really happening: the character rotates correctly, its transform points toward the mouse but it's no longer traveling along its x axis. It's going somewhere else. It seems to be off by 90 degrees but it's inconsistent.
    http://imgur.com/xvXPTHl

    I suspect the mistake is happening during the targetAngle calculation. If I click near to the right, where the angle change is minimal, it works. If I click behind the player, where the angle change is drastic, he goes careening off into outer space but he still faces the mouse click

    Unity masters, please help me.
    Does it have something to do with moving a rigidbody2D through translate instead of using the physics engine?
    Is there some glaring error in my logic or code that would be throwing off the angles?
    Why does my object seem to forget to travel along its transform.right?

    Here are a few more screenshots, these in engine to try to clarify. I've added a green ray to always point in transform.right to track the object's rotation.

    Here the click is slightly above the right. everything is in order
    http://imgur.com/QIO3cgk

    Here the click was above the player, resulting in absolute angle anarchy
    http://imgur.com/H0lieL2

    I realize this post was long. Thank you in advance.
     
  2. Wibber

    Wibber

    Joined:
    Dec 27, 2012
    Posts:
    12
    I use this Property to get the normalized face direction of entities from their rotation in my game.

    Code (csharp):
    1.  
    2.     public Vector2 DirectionVector { get { return(new Vector2 (Mathf.Cos (Mathf.Deg2Rad * transform.rotation.eulerAngles.z), Mathf.Sin (Mathf.Deg2Rad * transform.rotation.eulerAngles.z))).normalized; } }
    3.  
    This way you can just call
    Code (csharp):
    1.  
    2.  // move player along its positive x axis by speed.
    3.  transform.Translate (DirectionVector * moveSpeed * Time.deltaTime);
    4.  
    I can not guarantee that this is the best solution but it should work in your case.
     
    Last edited: May 21, 2014
  3. Valente11

    Valente11

    Joined:
    Sep 20, 2013
    Posts:
    12
    Strangely enough, the exact same problem is happening. As soon as the rotation angle changes more than ~60 degrees something gets thrown off and the object is no longer following the mouse, instead it travels at a slightly skewed angle. Might it be a bug, or some issue with the 2D physics? The code I pasted is verbatim what the object uses to move. Likewise, I used your code snipped (thank you for the alternate option, by the way) and it produced an identical result.

    The strange bit is that the rotation is always correct. The object is facing the mouse with a slight delay (intentional) through a Slerp. It's the traveling direction that gets thrown off. And stranger still is that it only gets thrown off if the mouse cursor clicks somewhere outside, say, 80 degrees to the right of the object. Another picture and I apologize for the crude drawings through which I communicate my ideas: http://imgur.com/iACEZUw
     
  4. Pyrian

    Pyrian

    Joined:
    Mar 27, 2014
    Posts:
    301
    I had a very similar issue that went away when I moved the code into FixedUpdate. There seems to be something glitchy about transform angles of Rigidbody2D's in Update calls; I'm not exactly sure what.

    I'll bet if you put everything but the Input call into FixedUpdate, your glitch will completely disappear. Just get and store the mouse position in Update, and do all the calculations in FixedUpdate.
     
  5. Valente11

    Valente11

    Joined:
    Sep 20, 2013
    Posts:
    12
    Hi Pyrian,

    I tried that option, but I'm sorry to say it did not work :(
     
  6. Pyrian

    Pyrian

    Joined:
    Mar 27, 2014
    Posts:
    301
    Well, I think it's time you added Debug calls to see where the values stop looking correct. What is the transform's rotation? And what is transform.right returning?
     
  7. Valente11

    Valente11

    Joined:
    Sep 20, 2013
    Posts:
    12
    Hi there, with some help from you guys and UnityAnswers, I was able to solve the problem.

    There was some problem with using transform.Translate combined with a rotation over time. Instead, I moved everything to FixedUpdate() and used rigidbody2D.AddForce. This, combined with adding a linear drag means that the object now swerves around to face the mouse.

    I'm currently playing with using Quaternion.RotateTowards instead of Slerp as it's not quite precise enough.

    I wanted to post the solution I found in case any future people encounter the same problem.