How do I get the Euler Angle difference from one object position to anothers orientation

1.8k views Asked by At

I'm looking to find the Euler angle difference (on one axis) between a targets position relative to the players orientation and position.

Hopefully the below image will help illustrate what I want.

Euler Angle

What I have attempted so far is this

    public GameObject player;
    public GameObject target;

    Vector3 targetDir = target.transform.position - player.transform.position;
    float angle = Vector3.Angle(player.transform.forward, targetDir);
    Debug.Log(angle);

This will output the angle between 0-180, no matter if its on the left and right.

What I want is the euler angle, so the angle should be represented between 0 to 360 degrees.

I have tried converting the angles to Quaternions but I'm getting inconsistent results. The number goes from very low to high with a small amount of movement in the console

var testRotation = Quaternion.FromToRotation(player.transform.forward,target.transform.position - player.transform.position);
Debug.Log(testRotation.eulerAngles.y);

I have tried doing this using vector3 and dot

  Vector3 targetDir = player.transform.position - target.transform.position;
    var rot = Mathf.Cos(Vector3.Dot(player.transform.forward, targetDir.normalized));
    Debug.Log(rot);

but this will output a number between 0.5 and 0.999

Using Draco18s answer I ended up creating this method (which is far from perfect). It worked for me.

/// <summary>
/// Calculate angle difference on the Y axis between one object (target) and anothers (player) orientation and position as an angle between 0 & 360 degrees
/// </summary>
/// <param name="_target"></param>
/// <param name="_player"></param>
/// <returns></returns>
private float CalcAngle(GameObject _target, GameObject _player)
{
    //Calculate the direction of the target removing any up or down rotation
    Vector3 _newDirection = (new Vector3(_target.transform.position.x, 0, _target.transform.position.z) - new Vector3(_player.transform.position.x, 0, _player.transform.position.z));

    // the vector that we want to measure an angle from
    Vector3 referenceForward = _player.transform.forward;/* some vector that is not Vector3.up */
    // Remove any up or down rotation
    referenceForward = new Vector3(referenceForward.x, 0, referenceForward.z);

    // the vector perpendicular to referenceForward (90 degrees clockwise)
    // (used to determine if angle is positive or negative)
    Vector3 referenceRight = _player.transform.right;
    referenceRight = new Vector3(referenceRight.x, 0, referenceRight.z);

    // Get the angle in degrees between 0 and 180
    float angle = Vector3.Angle(_newDirection, referenceForward);

    // Determine if the degree value should be negative. Here, a positive value
    // from the dot product means that our vector is on the right of the reference vector
    // whereas a negative value means we're on the left.
    float sign = Mathf.Sign(Vector3.Dot(_newDirection, referenceRight));

    // Create an angle between 0-360
    float result = sign * angle;
    if (result < 0)
    {
        result = 360 - Mathf.Abs(result);
    }
    //Give back the result
    return result;
}

Thanks

1

There are 1 answers

5
Draco18s no longer trusts SE On

I'm sure there's a dupe-target somewhere, but I can't find it.

I can, however, find some code that I got from...somewhere a number of years ago, complete with comments.

private float CalcAngle(Vector3 newDirection) {
    // the vector that we want to measure an angle from
    Vector3 referenceForward = transform.forward;/* some vector that is not Vector3.up */

    // the vector perpendicular to referenceForward (90 degrees clockwise)
    // (used to determine if angle is positive or negative)
    Vector3 referenceRight = transform.right;

    // Get the angle in degrees between 0 and 180
    float angle = Vector3.Angle(newDirection, referenceForward);

    // Determine if the degree value should be negative. Here, a positive value
    // from the dot product means that our vector is on the right of the reference vector
    // whereas a negative value means we're on the left.
    float sign = Mathf.Sign(Vector3.Dot(newDirection, referenceRight));

    return sign * angle;
}

This will give you a value from -180 to +180. Converting that to 0-360 will require a little math, but should be straight forward (hint: -179.99 -> +180.01).