Angles from quaternion/vector Problem.

I need to get the negative and positive angle from the current facing direction on the y axis/or x of the player and where the gun is aiming… and then make it do something if that angle is bigger than a certain degrees within 180 degrees.

My code is just not working out, and I need to get it on the specific axis too… HELP!

Here is the code as far as I could get:

// The current rotation of the player.

playerRotation = player.rotation;

//The weapon/gun look at target.

weapon.LookAt(target.position);

// The rotation of the weapon.// From this point onwards is where I mess up.

Quaternion wpRot = weapon.rotation;

//Get angle between player rotation and weapon rotation.

float wpRotAngle = Quaternion.Angle(playerRotation, wpRot);

if(wpRotAngle > 45){

//   do something....


}

This answer might be a little late, but in case anyone needs it:

If you are searching for the signed angle between two quaternions where you know the axis of rotation (since signed angles without known rotation axis make no sense) and assuming you actually only rotate around that arbitrary but specific axis, you can simply do the following:

  • Compute the Quaternion.ToAngleAxis of your current rotation that gives you the unsigned angle and the rotation axis in world space
  • Compute the Vector3.Angle between your known “axisOfRotation” (given in world space) and the computed rotation axis by Quaternion.ToAngleAxis
  • If Vector3.Angle is greater than 90° (usually 180°), you know that the computed axis by Quaternion.ToAngleAxis points the other way around.
  • Normalize the angle again to [-180,180] since one quaternion rotation cycle contains 720° (for example, from (1,0,0) to (-1,0,0))

Simple as that :slight_smile: Here goes the code:

public static float GetSignedAngle(Quaternion A, Quaternion B, Vector3 axis) {
	float angle = 0f;
	Vector3 angleAxis = Vector3.zero;
	(B*Quaternion.Inverse(A)).ToAngleAxis(out angle, out angleAxis);
	if(Vector3.Angle(axis, angleAxis) > 90f) {
		angle = -angle;
	}
	return Mathf.DeltaAngle(0f, angle);
}

Hope this works for anyone who reads this in future :slight_smile:

Note again: This code really assumes that you actually only rotate around the axis of rotation! Otherwise, the computed angle might not be correct anymore.

Cheers!

Quaternion.Angle will return the smallest angle connecting to two rotations with no regard to axes. The number will be in the range: 0 <= n <= 180

If you want the signed angles for each axes the you need to convert your rotations to euler angles:

private Vector3 EulerAnglesBetween(Quaternion from, Quaternion to) {
    Vector3 delta = to.eulerAngles - from.eulerAngles;

    if (delta.x > 180)
        delta.x -= 360;
    else if (delta.x < -180)
        delta.x += 360;

    if (delta.y > 180)
        delta.y -= 360;
    else if (delta.y < -180)
        delta.y += 360;

    if (delta.z > 180)
        delta.z -= 360;
    else if (delta.z < -180)
        delta.z += 360;

    return delta;
}

This starts with a simple difference then corrects the results to compensate for those cases when the smallest angle crosses the 0 degree / 360 degree threshold.

Each component of the Vector3 will be in the range: -180 <= n <= 180