Search code examples
unity-game-enginerotationquaternionsatan2

Object does not rotate in the correct direction from Atan2 to Quaternion


I am trying to rotate an object on its z axis, given a point I calculated at an angle with Atan2 function. Then I create a Quaternion to enter it in the rotation of the object. However, it does not rotate in the supposedly correct direction. If I diagram the angles given by the Atan2 functions, I visualize a clockwise system of angles, but if I diagram the angles that should be so that my object is rendered in the correct direction, I visualize an anti-clockwise system. The solutions creating a dictionary with the values received by the Atan2 function as keys and their values are the angles with which the object will rotate the correct direction. But I still don't understand what is happening. I hope someone can help me understand it because there is no worse solution than the one that solves but without knowing what is happening.

enter image description here

public class ArrowMovement : MonoBehaviour
{
    public Vector2Variable currentPlayerDirection;
    public Vector3Variable currentPlayerPosition;
    public InputAxis inputAxis;

    private float anglePassed;
    private Dictionary<float, float> realAngles = new Dictionary<float, float>();

    void Awake()
    {
        realAngles.Add(-135, -135);
        realAngles.Add(-90, 180);
        realAngles.Add(-45, 135);
        realAngles.Add(0, 90);
        realAngles.Add(45, 45);
        realAngles.Add(90, 0);
        realAngles.Add(135, -45);
        realAngles.Add(180, -90);
    }

    void Update()
    {
        Vector3 offsetVector = new Vector3(0.2f, 0.05f, 0);
        transform.position = currentPlayerPosition.Value;

        // Rotation
        float angle = Mathf.Atan2(inputAxis.horizontal, inputAxis.verticall) * Mathf.Rad2Deg;
        Quaternion rotation = Quaternion.Euler(0, 0, realAngles[angle]);
        transform.rotation = rotation;
    }
}

Solution

  • First of all, you should know what inputAxis is. I can guess from your diagram that you expect that for inputAxis.verticall == 0 the angle must be 0. Let's look at Mathf.Athan2(y,x) - it is equivalent to arctan(y/x), so result will be zero only when y is zero. But, in your code Mathf.Atan2(inputAxis.horizontal, inputAxis.verticall) will give 0 when inputAxis.horizontal == 0 - it is vertical direction (your first diagram).

    Second issue - wrong rotation direction. This can happen when one of the input axes is inverted. Probably, inputAxis is measured in a different coordinate system relative to your object, i.e. Z of your object is -Z of your inputAxis. Anyway, inputAxis.verticall can be inverted

    float angle = Mathf.Atan2(inputAxis.horizontal, -inputAxis.verticall) * Mathf.Rad2Deg;
    

    Also, you should avoid solving a simple geometric problem by "creating a dictionary" or anything like that. Even if you don't know how inputAxis works and result is wrong - make two step to fix it: 1. fix rotation direction - just invert the angle Quaternion.Euler(0, 0, -angle); 2. fix the zero position - add some static rotation. It is 90 deg in your case Quaternion.Euler(0, 0, 90 - angle). And it is the second way to solve the problem.