Search Unity

[SOLVED] Rotate around an object based on mouse position

Discussion in 'Scripting' started by PlazmaInteractive, Dec 16, 2016.

  1. PlazmaInteractive

    PlazmaInteractive

    Joined:
    Aug 8, 2016
    Posts:
    114
    I'm trying to make an object, in this case a paddle, to rotate around an orb in my game. Describing it as a 'controlled orbit' is probably the best way to get you guys to understand what I'm trying to achieve.

    Currently, I'm using a script I found online that correctly orbits the paddle automatically around the orb. I chose this because it allows me to adjust the radius of the orbit which I like. The only problem is I have no idea how to change it so that it orbits based on where my cursor/mouse is on the screen.

    Here's a GIF of the automatic orbit:
    ezgif.com-video-to-gif.gif

    And a GIF of what I'm trying to achieve. As you can see, it's using the automatic orbit I'm currently using but the way I'm moving my mouse around hopefully gives a picture of the 'controlled orbit':
    ezgif.com-video-to-gif (1).gif

    PaddleController script:
    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class PaddleController : MonoBehaviour
    4. {
    5.     public GameObject orb;
    6.     public float radius;
    7.     public float radiusSpeed;
    8.     public float rotationSpeed;
    9.  
    10.     private Transform centre;
    11.     private Vector3 desiredPos;
    12.  
    13.     void Start()
    14.     {
    15.         centre = orb.transform;
    16.         transform.position = (transform.position - centre.position).normalized * radius + centre.position;
    17.     }
    18.  
    19.     void Update()
    20.     {
    21.         transform.RotateAround(centre.position, Vector3.forward, rotationSpeed * Time.deltaTime);
    22.         desiredPos = (transform.position - centre.position).normalized * radius + centre.position;
    23.         transform.position = Vector3.MoveTowards(transform.position, desiredPos, radiusSpeed * Time.deltaTime);
    24.     }
    25. }
     
  2. PlazmaInteractive

    PlazmaInteractive

    Joined:
    Aug 8, 2016
    Posts:
    114
    UPDATE
    Well, I kinda managed to get the paddle to orbit based on mouse position, but only for the 'x' axis and it's not accurate. I want the paddle to look at the mouse accurately and rotate accurately too. So, if I move my mouse from left to right, the paddle should orbit and rotate left to right too.

    In the GIF below, you can see my paddle orbiting when I move my mouse along the 'x' axis. It's not accurate and also, if I moved my mouse in the 'y' axis, the paddle doesn't orbit or move at all.
    ezgif.com-video-to-gif.gif

    Updated script:
    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class PaddleController : MonoBehaviour
    4. {
    5.     public GameObject orb;
    6.     public float radius;
    7.     public float radiusSpeed;
    8.     public float rotationSpeed;
    9.  
    10.     private Transform centre;
    11.     private Vector3 desiredPos;
    12.  
    13.     void Start()
    14.     {
    15.         centre = orb.transform;
    16.         transform.position = (transform.position - centre.position).normalized * radius + centre.position;
    17.     }
    18.  
    19.     void Update()
    20.     {
    21.         float rotationX = Input.GetAxis("Mouse X") * -rotationSpeed;
    22.         transform.RotateAround(centre.position, Vector3.forward, rotationX);
    23.  
    24.         desiredPos = (transform.position - centre.position).normalized * radius + centre.position;
    25.         transform.position = Vector3.MoveTowards(transform.position, desiredPos, radiusSpeed * Time.deltaTime);
    26.     }
    27. }
     
    GileanVoid likes this.
  3. PlazmaInteractive

    PlazmaInteractive

    Joined:
    Aug 8, 2016
    Posts:
    114
    UPDATE
    I fixed the problem after researching online for a couple of hours. I founded this script, and added one line of code to include adjustable radius.

    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class PaddleController : MonoBehaviour
    4. {
    5.     public Transform orb;
    6.     public float radius;
    7.  
    8.     private Transform pivot;
    9.  
    10.     void Start()
    11.     {
    12.         pivot = orb.transform;
    13.         transform.parent = pivot;
    14.         transform.position += Vector3.up * radius;
    15.     }
    16.  
    17.     void Update()
    18.     {
    19.         Vector3 orbVector = Camera.main.WorldToScreenPoint(orb.position);
    20.         orbVector = Input.mousePosition - orbVector;
    21.         float angle = Mathf.Atan2(orbVector.y, orbVector.x) * Mathf.Rad2Deg;
    22.  
    23.         pivot.position = orb.position;
    24.         pivot.rotation = Quaternion.AngleAxis(angle - 90, Vector3.forward);
    25.     }
    26. }
    This is the final outcome:
    ezgif.com-video-to-gif.gif

    EDIT: It occurred to me during this that I didn't have enough knowledge when it comes to maths and programming. I'm pretty good with doing maths alone but applying it with programming is pretty confusing. Time to learn how to use maths with Unity3D and C#!
     
    Last edited: Dec 16, 2016
  4. deanpackard

    deanpackard

    Joined:
    Oct 25, 2017
    Posts:
    1
    This only works because your object you are rotating around is a circle. I tried implementing this in my own project, a 2D Platformer, where your gun rotates around you like a futuristic alien tech kinda thing. Here is a video explaining how I got this to work for me.

     
  5. CarterGrycko

    CarterGrycko

    Joined:
    Apr 29, 2017
    Posts:
    2
    Thanks for making this video I was having exactly the same problem and was lost
     
  6. Deccade

    Deccade

    Joined:
    Apr 12, 2020
    Posts:
    2
    how would I do this instead of the mouse it's A and D?
     
  7. Wrimor

    Wrimor

    Joined:
    Oct 27, 2017
    Posts:
    3
    Hi, here's a simple implementation of the script using keyboard input:

    Code (CSharp):
    1.  
    2.    public Transform orb;
    3.     public float radius;
    4.  
    5.     private Transform pivot;
    6.  
    7.     float curAngle;
    8.     void Start()
    9.     {
    10.         pivot = orb.transform;
    11.         transform.parent = pivot;
    12.         transform.position += Vector3.up * radius;
    13.         curAngle = 0;
    14.     }
    15.  
    16.     void Update()
    17.     {
    18.       if(Input.GetKey(KeyCode.Q))
    19.         {
    20.             curAngle += 0.5f;
    21.         }
    22.         else if(Input.GetKey(KeyCode.E))
    23.         {
    24.             curAngle -= 0.5f;
    25.         }
    26.        pivot.rotation = Quaternion.AngleAxis(curAngle, Vector3.forward);
    27.     }
    28. }
     
  8. uwukirb

    uwukirb

    Joined:
    Mar 21, 2022
    Posts:
    1
    I cannot read your code very well is it possible to put it in the description of your video?
     
  9. FRAGt4g

    FRAGt4g

    Joined:
    Oct 9, 2021
    Posts:
    1
    I have an easier solution and it works for any gameobject. All you have to do is take the vector from between the mouse and the pivot and normalize it. That will give you the direction the object needs to be; then take that and multiply it by the radius of the circle. Then set the position of the rotating object to that vector + the position of the pivot.

    Here is the code:
    rotating object's position = (Vector2)(pivot.position + ("vector between the mouse and pivot".normalized * radius));
     
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    And here is my treatment, two ways of spinning a dial. Full package enclosed.
     

    Attached Files:

  11. Veteran66

    Veteran66

    Joined:
    Jul 12, 2015
    Posts:
    50
    Hi Kurt

    i use your RotateZ, in my Project (3D) i must rotate the Y Axis with Mouse 1 and Alt Button.
    How i can change this?
     
  12. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    This is the code:

    Code (csharp):
    1.     void PerformCircularRotation()
    2.     {
    3.         // where is our center on screen?
    4.         Vector3 center = Camera.main.WorldToScreenPoint(transform.position);
    5.  
    6.         // angle to previous finger
    7.         float anglePrevious = Mathf.Atan2(center.x - lastPosition.x, lastPosition.y - center.y);
    8.  
    9.         Vector3 currPosition = Input.mousePosition;
    10.  
    11.         // angle to current finger
    12.         float angleNow = Mathf.Atan2(center.x - currPosition.x, currPosition.y - center.y);
    13.  
    14.         lastPosition = currPosition;
    15.  
    16.         // how different are those angles?
    17.         float angleDelta = angleNow - anglePrevious;
    18.  
    19.         // rotate by that much
    20.         transform.Rotate(new Vector3(0, 0, angleDelta * Mathf.Rad2Deg));
    21.     }
    I'm thinking the changes would be:

    - change the angleDelta to pass in as the Y instead of the Z (line 20)

    That would probably work straight up. Obviously orient the camera downwards.

    It might require you inverting (negating) one or both of the input axes, OR possibly inverting the sign of the rotation... just fiddle with it.
     
  13. Veteran66

    Veteran66

    Joined:
    Jul 12, 2015
    Posts:
    50
    sorry, not work
     
  14. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    That's not useful. I told you the necessary steps. It is up to you to do the engineering.

    - understand how the first one works (the code is provided)

    - understand what axes get swapped / inverted for your version of the problem.

    - adapt and change the code

    - test and iterate above until it works.
     
  15. TheDevloper

    TheDevloper

    Joined:
    Apr 30, 2019
    Posts:
    69
    Great work man, you fixed the issue, good luck