# Issue with script recognizing particular z-axis rotation angles in Unity

I'm trying to make a simple flowing pipe-style rotation puzzle, but having issues getting Unity to properly recognize certain angles of rotation. My rotation script for the pieces:

private void OnMouseDown() { if (!GameControl.winState) transform.Rotate(0f, 0f, 90f); }

If the value of the z rotation is set to 90 or -90, the game works fine. However, if I try a different value such as 60 or 30 (and have corresponding 60 or 30 shifts to the puzzle hexes' z rotations to scramble the puzzle), the game fails to note a win state. Here is the game control script:

public Transform[] hex;
public GameObject successLight;

public static bool winState;

void Start () {
successLight.SetActive(false);
winState = false;
}

void Update ()
{
if (hex[0].rotation.z == 0
&& hex[1].rotation.z == 0
&& hex[2].rotation.z == 0
&& hex[3].rotation.z == 0
&& hex[4].rotation.z == 0)
{
Debug.Log("PuzzleSolved!");
winState = true;
successLight.SetActive(true);
}
}


I've also tried making the rotation using Euler angles, but still experienced the same problem. Is this an issue with the rotation not being exact and therefore unable to meet the conditions? Checking the inspector as the game runs, it looks as if even when the hexes all get to the proper z rotation of 0, the win state still isn't triggering when the rotation moves at a degree other than 90. Any help would be appreciated, feeling very confused at the moment.

hex[0].rotation.z == 0

Here you're looking for z to be a rotation angle, but it's not. A Transform's .rotation property is a quaternion, not an Euler angle triplet. Picking out one of the four components of a quaternion individually is rarely meaningful.

You could query the eulerAngles or localEulerAngles properties instead to get angle triplets, but I'd recommend getting out of the habit of picking out individual angles for game calculations - it leads many devs to avoidable errors, because our expectations of how the angles should behave are not well-calibrated to how they actually do.

Instead a safer method might be this:

// Expose the solution angle values as an Inspector-editable array.
public float[] solutionAngles = new float[]{0,0,0,0,0};
Quaternion[] solutionRotations;

void Start() {
// Cache our solutions as quaternion rotations.
solutionRotations = new Quaternion[solutionAngles.Length];
for(int i = 0; i < solutionAngles.Length; i++)
solutionRotations = Quaternion.Euler(0, 0, solutionAngles[i]);

successLight.SetActive(false);
winState = false;
}

void Update() {
// If any hex doesn't match its solution rotation, early-out.
for(int i = 0; i < solutionRotations.Length; i++) {
if(hex[i].rotation != solutionRotations[i])
return;
}

// If we get here, then all solution rotations match.
Debug.Log("PuzzleSolved!");
winState = true;
successLight.SetActive(true);
}


Doing it this way, our code is insensitive to differences in angular notation - like wither to call an angle -90 or +270 - and also has a little wiggle room for floating point rounding, since the quaternion == looks for an approximate match.

• Thank you for the answer, this is extremely helpful in understanding the finicky nature of angles and rotation in Unity! It's now working occasionally, which is a big improvement on it not working at all. Some of the hexes are needing multiple full rotations for the 0 to register as 0 or still not registering consistently, so I'm thinking of adding some other variable to track position/number of clicks from the base rotation and just using the rotation values for visual feedback. – trevor Mar 3 '19 at 15:37
• You might be landing slightly off zero. Instead of ==, you can use Quaternion.Angle to measure the difference between two orientations and apply your own threshold. – DMGregory Mar 3 '19 at 15:42
• Thanks for the suggestion, it's working consistently now with no issues. – trevor Mar 3 '19 at 15:53