# Lock Z axis from the gyroscope rotation

Here's the code I use.

public class CameraGyro : MonoBehaviour {

private float initialX;
private float initialY;
private float initialZ;

// Use this for initialization
void Start () {
Input.gyro.enabled = true;

initialX = Input.gyro.rotationRateUnbiased.x;
initialY = Input.gyro.rotationRateUnbiased.y;
}

// Update is called once per frame
void Update () {

transform.Rotate (initialX - Input.gyro.rotationRateUnbiased.x, initialY - Input.gyro.rotationRateUnbiased.y, 0f);
}

}


The thing is when I rotate the phone, the Z axis seems to change even if I've set it to 0f in the code above. Is there a way to really lock this position to 0?

• What do you mean "seems to change"? Feb 23 '16 at 21:07
• Well the Z axis change value when it's supposed to stay at 0 Feb 23 '16 at 21:15
• are you measuring that changed based on how the transform rotates or externally? Feb 23 '16 at 21:40
• you are talking about the Z translate value or Z rotation value? Which is changing and supposed not to change? Feb 24 '16 at 6:09
• Simple explanation... I need to make the gyroscope work by only rotating the X and Y axis. Z should be locked. Feb 24 '16 at 14:33

I'm rotating an object on two axes, so why does it keep twisting around the third axis?

The root issue here is that the idea that rotation is naturally/objectively separable into 3 independent components (the way we can do with translation) is a misconception.

Euler angles / Tait-Bryan angles lure us into this belief because they look a lot like a translation vector, but it's easy to show that it's false. Consider the angle triplets (180, 180, 0) and (0, 0, 180): both represent the same orientation, one purely with "x & y" rotations, the other with "purely z" rotation. Or here's another example with compounding rotations in sequence:

So, zeroing-out the z component of an angular triplet isn't enough to guarantee you don't get roll.

What to do instead depends on the exact behaviour you want. You could try for instance track a pitch & yaw value independently, and apply the total all at once rather than incrementally compounding rotations:

// in Start(), initialize your x & y angles to match the camera's initial orientation.
pitch = transform.eulerAngles.x;
yaw = transform.eulerAngles.y;

// In Update, accumulate rotational change in these axes:
pitch += input.gyro.rotationRateUnbiased.x * Mathf.RadToDeg() * Time.deltaTime;
yaw += input.gyro.rotationRateUnbiased.y * Mathf.RadToDeg() * Time.deltaTime;
// Apply the result all at once:
transform.eulerAngles = new Vector3(pitch, yaw, 0);


Or you could try rotating the forward / look vector, then construct a "roll-free" orientation that looks in that direction:

Vector3 angularDelta = input.gyro.rotationRateUnbiased * Time.deltaTime;
Vector3 newForward = transform.forward + Vector3.Cross(transform.forward, angularDelta);
transform.rotation = Quaternion.LookRotation(newForward);


Try locking the z axis using "Rotation Constraints": https://docs.unity3d.com/Manual/class-RotationConstraint.html

• This answer would be better if it explained how the behaviour of this component differs from manually setting the angle increment to zero. Dec 16 '18 at 22:03