Get angle from mouse direction?

I have an object that I wish to rotate at the same angle as the mouse movement direction. I have used the following code:

mouseLeftRight = Input.GetAxis ("Mouse X") * 1.5f;
mouseUpDown = Input.GetAxis ("Mouse Y") * 1.5f;
    
angle = Mathf.Atan2 (mouseUpDown, mouseLeftRight) * Mathf.Rad2Deg;
if (angle<0) angle += 360;
    
transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x,
transform.localEulerAngles.y, 
angle);

Debug.Log shows me that the angle is suitable; If I move the mouse right, angle is 0, up and angle is 90, left and angle is 180, down and angle is 270.

The object I am applying the rotation to sometimes works as expected, although jittery, but most of the time it just spins rapidly on its local Z-axis as if a rotation is being constantly added. When it does this, debug.log tells me that the transform.localEulerAngles.z of the object = 0.

I do not understand why it is doing this. Can anyone help?

The reason it is jittery and not as you expect is because Input.GetAxis () returns you the mouse delta for the previous frame. You’re using it to set absolute rotation. This can cause a lot of jittery movement.

Consider a mouse movement towards 45° (up and to the right). Let’s assume it happens over the course of two frames. One user executes a smooth mouse movement, and each frame the delta mouse movement is (1, 1). Another user executes a slightly jittery mouse movement, and the first frame the delta mouse movement is (2, 0) and the next frame the delta mouse movement is (0, 2).

User 1 does something like this: 20448-1-step.png

User 2 does something like this: 20449-2-step.png

In the code that you’ve presented, the first user will see what they want (the object rotated nicely to 45°). The second user will probably see something jittery and unsatisfying. The first frame the cylinder will rotate to 0° (because of the (2,0) delta mouse movement). The second frame the cylinder will rotate to 90° (because of the (0, 2) delta mouse movement). For both users, on the third frame (when they’ve stopped moving the mouse) the cylinder will rotate back to 0°. Unfortunately, when it comes to mouse movement, we are pretty much all user 2.

To get what you want, you need to use mouse deltas to apply rotation deltas, or mouse absolute distance from a reference point to apply absolute rotation. A quick example of the “absolute” solution is below. This solution waits for the user to click the mouse before applying any rotation. When the user first presses the mouse button down, we set the “origin” of the movement at the current mouse location. As the user moves the mouse (keeping the mouse button held down), we compare the mouse position to the origin that we set at the beginning of the drag. We use this “absolute” mouse position to set an absolute rotation value.

public class Rotation : MonoBehaviour {

	private Vector3 startPosition;

	void Update() {
		
		if (Input.GetMouseButtonDown(0))
		{
			startPosition = Input.mousePosition;
		}
		
		if (Input.GetMouseButton(0))
		{
			Vector3 mouseDelta = Input.mousePosition - startPosition;
			
			if (mouseDelta.sqrMagnitude < 0.1f)
			{
				return; // don't do tiny rotations.
			}
			
			float angle = Mathf.Atan2 (mouseDelta.y, mouseDelta.x) * Mathf.Rad2Deg;
			if (angle<0) angle += 360;
			
			Debug.Log (angle);
			
			transform.localEulerAngles = new Vector3 (transform.localEulerAngles.x,
			                                          transform.localEulerAngles.y, 
			                                          angle);
		}
	}
}