Quaternion.Angle() unexpected output. Compare to Vector3.Angle() which produces correct values.
I'm struggling to understand output from Quaternion.Angle(). The docs say it "Returns the angle in degrees between two rotations a and b." But it produces a value that I do not expect. To illustrate this, below is a script that applies the same rotations to Vector3s (that represent a direction, not euler angles.) and uses Vector3.Angle() in a way that produces the correct result, and that I think should also be returned from Quaternion.Angle().
Why are qAngle and vAngle_Q different? or qAngle_Down and vAngle_Q_Down?
Am I misunderstanding what Quaternion.Angle() does, or is it broken?
 using System;
 using System.Collections.Generic;
 using UnityEngine;
 
 namespace WFR.VRPack
 {
     class QTest : MonoBehaviour
     {
         [SerializeField] private Vector3 eulerAnglesInput = new Vector3(45, 30, 0);
 
         [ContextMenu("Q Test")]
         private void DoQTest()
         {
             string stringLog = "";
 
             stringLog +=
                 "identity:" + "\n" +
                 "A:" + Quaternion.identity.eulerAngles + "\n" +
                 "Q:" + Quaternion.identity + "\n" +
                 "V:" + Quaternion.identity * Vector3.forward + "\n" +
                 "";
 
             Quaternion quatFromEuler = Quaternion.Euler(eulerAnglesInput);
             Vector3 vecFromQuat = quatFromEuler * Vector3.forward;
             Vector3 vecFromEuler = Vector3.forward;
                     // Unity uses euler order Y - X - Z.
                     // Manually perform Y rotation.
                     vecFromEuler = Quaternion.AngleAxis(eulerAnglesInput.y, Vector3.up) * vecFromEuler;
                     // Manually perform X rotation. Unity is a left handed coordinate system, so Vector3.up comes first.
                     Vector3 newVector3Right = Vector3.Cross(Vector3.up, vecFromEuler);
                     vecFromEuler = Quaternion.AngleAxis(eulerAnglesInput.x, newVector3Right) * vecFromEuler;
                     // Manually perform z rotation.
                     // Note: In this simple test without a gameobject where the vector represents forward, it makes no difference to rotate around forward.
                     Vector3 newVector3Forward = vecFromEuler;
                     vecFromEuler = Quaternion.AngleAxis(eulerAnglesInput.z, newVector3Forward) * vecFromEuler;
             
             stringLog += "\n";
             stringLog +=
                 "input:" + "\n" +
                 "eulerAnglesInput: " + eulerAnglesInput + "\n" +
                 "quatFromEuler:    " + quatFromEuler + "\n" +
                 "vecFromQuat:      " + vecFromQuat + "\n" +
                 "vecFromEuler:     " + vecFromEuler + "\n" +
                 "";
 
             float qAngle = Quaternion.Angle(Quaternion.identity, quatFromEuler);
             float vAngle_Q = Vector3.Angle(Quaternion.identity * Vector3.forward, vecFromQuat);
             float vAngle_E = Vector3.Angle(Quaternion.identity * Vector3.forward, vecFromEuler);
 
             stringLog += "\n";
             stringLog +=
                 "output:" + "\n" +
                 "qAngle:   " + qAngle + "\n" +
                 "vAngle_Q: " + vAngle_Q + "\n" +
                 "vAngle_E: " + vAngle_E + "\n" +
                 "";
 
             Quaternion quatDown = Quaternion.FromToRotation(Vector3.forward, Vector3.down);
             float qAngle_Down = Quaternion.Angle(quatDown, quatFromEuler);
             float vAngle_Q_Down = Vector3.Angle(quatDown * Vector3.forward, vecFromQuat);
             float vAngle_E_Down = Vector3.Angle(quatDown * Vector3.forward, vecFromEuler);
             
             stringLog += "\n";
             stringLog +=
                 "output:" + "\n" +
                 "qAngle_Down:   " + qAngle_Down + "\n" +
                 "vAngle_Q_Down: " + vAngle_Q_Down + "\n" +
                 "vAngle_E_Down: " + vAngle_E_Down + "\n" +
                 "";
 
             Debug.Log(stringLog);
         }
 
     }
 }
 
sample output:
 identity:
 A:(0.0, 0.0, 0.0)
 Q:(0.0, 0.0, 0.0, 1.0)
 V:(0.0, 0.0, 1.0)
 
 input:
 eulerAnglesInput: (45.0, 30.0, 0.0)
 quatFromEuler:    (0.4, 0.2, -0.1, 0.9)
 vecFromQuat:      (0.4, -0.7, 0.6)
 vecFromEuler:     (0.4, -0.7, 0.6)
 
 output:
 qAngle:   53.64744
 vAngle_Q: 52.23875
 vAngle_E: 52.23876
 
 output:
 qAngle_Down:   53.64743
 vAngle_Q_Down: 45
 vAngle_E_Down: 45
 
 
Your answer
 
 
             Follow this Question
Related Questions
Quaternions to EulerAngles weird x-axis interaction 1 Answer
Avoiding Gimbal Lock with Vector3 EulerAngles and Applying Torque 0 Answers
How to add to a rotation angle? 0 Answers
Any simple ways of keeping track of simple rotation? 2 Answers
Order of the rotations around the axes with Euler angles 1 Answer
 koobas.hobune.stream
koobas.hobune.stream 
                       
               
 
			 
                