Just stuck on this problem and I feel there must be a good solution.

I’m trying to get the delta angle for a single axis (in this case Z) in the object’s local coordinate space. I found a good solution for XY, ZX, XZ in world space (here) but I can’t seem to convert it to the object’s local space.

Any ideas what I might be doing wrong here?

public Transform ParentObject;
Quaternion DeltaRotation;
void FixedUpdate () {
//Rotate test object around Z
ParentObject.transform.RotateAroundLocal(ParentObject.transform.TransformDirection(new Vector3(0,0,1)), 2*Time.deltaTime);
//Check the angle difference in z
GetAngleOffset(ParentObject.rotation, DeltaRotation);
//Update the delta rotation
DeltaRotation = ParentObject.rotation;
}
void GetAngleOffset(Quaternion rotationA, Quaternion rotationB){
// get a "vector" for each rotation
var RelativeA = rotationA * ParentObject.transform.InverseTransformDirection(new Vector3(0,1,0));
var RelativeB = rotationB * ParentObject.transform.InverseTransformDirection(new Vector3(0,1,0));
//Get both angles
var angleA = Mathf.Atan2(RelativeA.y, RelativeA.x) * Mathf.Rad2Deg;
var angleB = Mathf.Atan2(RelativeB.y, RelativeB.x) * Mathf.Rad2Deg;
// get the signed difference in these angles
var angleDiff = Mathf.DeltaAngle( angleA, angleB );
Result = (angleDiff);
}

Incase you don’t want to mess with quaternions (difficult to understand) you could try this vector-based version.

public static class ExtensionMethods_Vector
{
public static float SignedAngle(this Vector3 referencepoint, Vector3 from, Vector3 to, Vector3 referenceup)
{// calculates the the angle between two vectors regarding to a reference point (plane), with a referenceup a sign in which direction it points can be calculated (clockwise is positive and counter clockwise is negative), source: Henry
Vector3 fromdir = from - referencepoint; // calculate the directionvector pointing from refpoint towards frompoint
Vector3 todir = to - referencepoint; // calculate the directionvector pointing from refpoint towards topoint
Vector3 planenormal = Vector3.Cross(fromdir, todir); // calculate the planenormal (perpendicular vector)
float angle = Vector3.Angle(fromdir, todir); // calculate the angle between the 2 direction vectors (note: its always the smaller one smaller than 180°)
float orientationdot = Vector3.Dot ( planenormal, referenceup ); // calculate wether the normal and the referenceup point in the same direction (>0) or not (<0), http://docs.unity3d.com/Documentation/Manual/ComputingNormalPerpendicularVector.html
if (orientationdot > 0.0f) // the angle is positive (clockwise orientation seen from referenceup)
return angle;
return -angle; // the angle is negative (counter-clockwise orientation seen from referenceup)
}
}

Hey thanks for posting that up, sorry but I’m not sure I know how to use it correctly.
Just not sure about the arguments - is the first one a position value? Then the from and to, are they eulers or points in space?
Thanks,
Pete

They are position vectors. The first two lines calculate both directions out of them. Referenceup is a direction vector. Could have been more clear when they wre named frompoint and topoint. I have changed that in my codebase.
You could easily turn it in a direction based method when you leave out the first two lines and use the from and two directly as directions to use it directly with transform.foward fe. I have also added this method in my codebase.

public static class ExtensionMethods_Vector
{
public static float SignedAngleFromPosition(this Vector3 referencepoint, Vector3 frompoint, Vector3 topoint, Vector3 referenceup)
{// calculates the the angle between two position vectors regarding to a reference point (plane), with a referenceup a sign in which direction it points can be calculated (clockwise is positive and counter clockwise is negative)
Vector3 fromdir = frompoint - referencepoint; // calculate the directionvector pointing from refpoint towards frompoint
Vector3 todir = topoint - referencepoint; // calculate the directionvector pointing from refpoint towards topoint
Vector3 planenormal = Vector3.Cross(fromdir, todir); // calculate the planenormal (perpendicular vector)
float angle = Vector3.Angle(fromdir, todir); // calculate the angle between the 2 direction vectors (note: its always the smaller one smaller than 180°)
float orientationdot = Vector3.Dot ( planenormal, referenceup ); // calculate wether the normal and the referenceup point in the same direction (>0) or not (<0), http://docs.unity3d.com/Documentation/Manual/ComputingNormalPerpendicularVector.html
if (orientationdot > 0.0f) // the angle is positive (clockwise orientation seen from referenceup)
return angle;
return -angle; // the angle is negative (counter-clockwise orientation seen from referenceup)
}
public static float SignedAngleFromDirection( this Vector3 fromdir , Vector3 todir , Vector3 referenceup )
{// calculates the the angle between two direction vectors, with a referenceup a sign in which direction it points can be calculated (clockwise is positive and counter clockwise is negative)
Vector3 planenormal = Vector3.Cross( fromdir , todir ); // calculate the planenormal (perpendicular vector)
float angle = Vector3.Angle( fromdir , todir ); // calculate the angle between the 2 direction vectors (note: its always the smaller one smaller than 180°)
float orientationdot = Vector3.Dot( planenormal , referenceup ); // calculate wether the normal and the referenceup point in the same direction (>0) or not (<0), http://docs.unity3d.com/Documentation/Manual/ComputingNormalPerpendicularVector.html
if( orientationdot > 0.0f ) // the angle is positive (clockwise orientation seen from referenceup)
return angle;
return -angle; // the angle is negative (counter-clockwise orientation seen from referenceup)
}
}
// usage:
float angle = transform.forward.SignedAngleFromDirection( transform.right , transform.up); // == 90 degrees