Search Unity

Move object perpendicular to the mouse position

Discussion in '2D' started by Bogaland, Feb 25, 2017.

  1. Bogaland

    Bogaland

    Joined:
    Feb 19, 2017
    Posts:
    32
    In my code I have the player moving towards the mouse position when I press W and from the mouse position when pressing S. I also want the player to move left and right when I press A and D. However, I don't want the player to move left and right according to the X and Y-plane but relative to where the player is to the mouse position (the player rotates towards the mouse position at all times). So basically, when the player is rotated I want it to move perpendicular to it's direction to the mouse position when I press A or D.

    This is my code for moving to/from the mouse:

    Code (CSharp):
    1.      void Update()
    2.         {
    3.             if (Input.GetKey(KeyCode.W))
    4.             {
    5.                 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    6.                 target.z = transform.position.z;
    7.                 transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);
    8.             }
    9.             if (Input.GetKey(KeyCode.S))
    10.             {
    11.                 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    12.                 target.z = transform.position.z;
    13.                 transform.position = Vector3.MoveTowards(transform.position, target, -speed * Time.deltaTime);
    14.             }
    15.         }
    It also rotates using the following code:

    Code (CSharp):
    1.     void Update()
    2.         {
    3.             //rotation
    4.             Vector3 mousePos = Input.mousePosition;
    5.             mousePos.z = 0;
    6.  
    7.             Vector3 objectPos = Camera.main.WorldToScreenPoint(transform.position);
    8.             mousePos.x = mousePos.x - objectPos.x;
    9.             mousePos.y = mousePos.y - objectPos.y;
    10.  
    11.             float angle = Mathf.Atan2(mousePos.y, mousePos.x) * Mathf.Rad2Deg;
    12.             angle -= 90;
    13.             transform.rotation = Quaternion.Euler(new Vector3(0, 0, angle));
    14.             }
    15.         }
     
  2. Ruim

    Ruim

    Joined:
    Jul 4, 2013
    Posts:
    3
    Calculate the Vector3 from the player to the mouse and then the perpendicular vector. Following code is not tested but should be something like this:
    1. Vector3 mousePos = Input.mousePosition;
    2. mousePos.z = 0;
    3. Vector3 objectPos = Camera.main.WorldToScreenPoint(transform.position);
      Vector3 perp = new Vector3(objectPos..y, objectPos.x, 0);
      Vector3 move = perp.normalized * speed;


      When pressing the left/right keys you have to move either along the "move" vector or the opposite direction.
      Hope it helps
     
  3. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    It's missing a negation.
    Either clockwise:
    Code (CSharp):
    1. Vector3 perp = new Vector3(objectPos.y, -objectPos.x, 0);
    Or counter-clockwise
    Code (CSharp):
    1. Vector3 perp = new Vector3(-objectPos.y, objectPos.x, 0);
     
  4. Bogaland

    Bogaland

    Joined:
    Feb 19, 2017
    Posts:
    32
    It's not really working. I think you made a mistake to begin with, since you never actually calculate the vector between the mouse and the object's position. I redid the code a bit and got this:

    Code (CSharp):
    1. Vector3 mousePos = Input.mousePosition;
    2.         mousePos.z = 0;
    3.         Vector3 objectPos = Camera.main.WorldToScreenPoint(transform.position);
    4.         Vector3 n1 = mousePos - objectPos;
    5.         Vector3 perp = new Vector3(n1.y, n1.x, 0);
    and then:

    Code (CSharp):
    1. if (Input.GetKey(KeyCode.A))
    2.         {
    3.             transform.position = Vector3.MoveTowards(transform.position, -perp, speed * Time.deltaTime);
    4.         }
    5.         else if (Input.GetKey(KeyCode.D))
    6.         {
    7.             transform.position = Vector3.MoveTowards(transform.position, perp, speed * Time.deltaTime);
    8.         }
    It works as long as the player is moving along the x and y-axis. However, if I'm moving 45 degrees (my player always follows the mouse position) it's not working. Then the player just continues to walk towards/from the mouse if I press A or D.
     
  5. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    You also forgot what I had mentioned above. You have to not only switch, but also invert either the x or the y value.

    I've written a quick example, which at least uses the correct perpendicular (clockwise) vector on a per-frame basis. If you want to eliminate the "rotate around" effect when you move sideways , you can do that of course.

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class CLASS_NAME : MonoBehaviour
    4. {
    5.     private Camera _mainCamera;
    6.  
    7.     [SerializeField]
    8.     private float speed = 2f;
    9.  
    10.     private void Awake()
    11.     {
    12.         _mainCamera = Camera.main;
    13.     }
    14.  
    15.     private void Update()
    16.     {
    17.         var mouseWorldPosition = _mainCamera.ScreenToWorldPoint(Input.mousePosition);
    18.         mouseWorldPosition.z = 0f; // this should actually be transform.position.z in case your sprite is not located at z = 0
    19.         // this is one way to rotate, right (x-axis) being the new forward
    20.         transform.right = (mouseWorldPosition - transform.position);
    21.    
    22.         var movementVector = GetMovementVector();
    23.         transform.Translate(movementVector * Time.deltaTime * speed);
    24.     }
    25.  
    26.     private Vector2 GetMovementVector()
    27.     {
    28.         Vector2 movementDirection = Vector2.zero;
    29.    
    30.         // accumulates the input, use else if to only enable one key at a time
    31.         if (Input.GetKey(KeyCode.A))
    32.         {
    33.             movementDirection.y -= 1f;
    34.         }
    35.         if (Input.GetKey(KeyCode.D))
    36.         {
    37.             movementDirection.y += 1f;
    38.         }
    39.         if (Input.GetKey(KeyCode.W))
    40.         {
    41.             movementDirection.x += 1f;
    42.         }
    43.         if (Input.GetKey(KeyCode.S))
    44.         {
    45.             movementDirection.x -= 1f;
    46.         }
    47.    
    48.         return movementDirection.normalized;
    49.     }
    50. }
     
    Last edited: Feb 26, 2017
  6. Ruim

    Ruim

    Joined:
    Jul 4, 2013
    Posts:
    3
    Yes you are right :) I wrote it a bit in a hurry (sorry).
     
  7. Suddoha

    Suddoha

    Joined:
    Nov 9, 2013
    Posts:
    2,824
    Wasn't meant to be offending in any way. So there's no reason to say sorry :) Don't worry, we're all kind persons. :)
     
  8. Ruim

    Ruim

    Joined:
    Jul 4, 2013
    Posts:
    3
    I didn't take it that way. Glad you got it working :)