How would I interpret angular displacement from target rotation to max out at 180°?

I have two rotations, the objects current rotation, and the target objects rotation. I would like to create a single float that increases as the two rotations differ maxing out at 180° (facing opposite directions). I spent a long time looking into options and found “ToAngleAxis”. This lets me grab a single number for the rotations and use that to find the difference.

Bear with me as this gets a little confusing - but the problem is that when the object is facing the opposite direction the displacement is 180° - but if it continues to rotate towards the target rotation it goes all the way to 360° instead of back down to zero.

Anyone have any ideas on how to get the displacement to max out at 180° and go back down to zero as it turns in a full circle?

Here’s my code that will work with two cubes if you want to test out my problem:

    public Transform target;
    float curAngle;
    Vector3 curAxis;
    float targAngle;
    Vector3 targAxis;

    void Update () {
        transform.rotation.ToAngleAxis(out curAngle, out curAxis);
        target.rotation.ToAngleAxis(out targAngle, out targAxis);
        double displacement = 1-(curAngle-targAngle);

Aren’t rotations FUN?!??!?

In case anyone is wondering WHY I’m trying to do this – I’d love to sync the pitch of an audio source to how closely it’s looking towards the player.

Hey @wyatts!
I’m not sure this is what you want, but Quaternion.Angle() gives you the angle between 2 rotations, clamped to a value between 0 and 180, so if you divide it by 180 you’ll get a float between [0, 1], maxing out at 180.

Maybe you can use the vector dot product to achieve what you want. Vector3.Dot returns a float between 1 and -1 for normalized vectors. -1 meaning they are pointing in opposite directions, i.e 180deg apart:

Thanks Harinezumi! Wow I can’t believe I overlooked this. Such a simple tool!!! Definitely simplifies my approach, yet it returned the same result (it goes to 360 instead of maxing out at 180). I actually found a nice bit of code that just maths the numbers over 180 back down :slight_smile:

    public Transform target;
    public float angleOut;

    void Update () {
        var displacement = Quaternion.Angle(target.rotation, transform.rotation);
        angleOut = ClampAngle(displacement, 0, 180);

    float ClampAngle(float angle, float from, float to) {
        if(angle >180) angle = 360 - angle;
        angle = Mathf.Clamp(angle, from, to);
        if(angle <0) angle = 360 + angle;
        return angle;