Problem with localEulerAngles (180 degrees error?)


I just started learning Unity and I got a problem: I want to rotate a wheel around X axis (simulate movement) and around Y axis (simulate steering), using the following code:

wheel.Rotate(collider.rpm * 6 * Time.deltaTime, 0, 0);  //rotate around X  
wheel.localEulerAngles = new Vector3(wheel.localEulerAngles.x, collider.steerAngle, wheel.localEulerAngles.z); //rotate around Y

The problem is with wheel.localEulerAngles.z : sometimes it returns -1 or -2 and sometimes 180. - and this makes my wheel rotate on Z axis about 180 degrees constantly, something that I don’t want. If I try to modify it’s value (for example add only the values which are lower than 180) it “partially” fixes it but the wheel is not rotating correctly on the X axis.

Any simple solution is greatly appreciated.

*simple = not-very-complicated quaternions or no quaternions at all

The conversion quaternion->euler isn’t reliable: there are several different xyz combinations corresponding to any quaternion, and many times the combination returned isn’t the one we expect - specially when more than one axis is != zero.

Fortunately, the conversion euler->quaternion is reliable, thus we can use the following approach: get the initial Euler angles and rotate them mathematically, assigning the result to the actual Euler angles in Update (or other periodic function):

Vector3 euler;

void Start(){
  euler = wheel.localEulerAngles; // save initial rotation

void Update(){
  // "rotate" wheel angle around X:
  euler.x = (euler.x + collider.rpm * 6 * Time.deltaTime) % 360;
  // set wheel Y angle:
  euler.y = collider.steerAngle;
  // update actual wheel localEulerAngles:
  wheel.localEulerAngles = euler;

NOTE: This works fine because Unity applies the Euler rotations in the order Z-X-Y, thus the angle about X will be set before the angle about Y. This trick would fail if the wheel rotated about Y and steered about X, for instance.

As a general rule, never modify localEulerAngles directly. Use quaternions instead.

IMO when it comes to coding, Euler angles are more complicated than quaternions, since there are so many friggin’ exceptions you need to consider to avoid a gimbal lock.

Although I cannot give you a simple answer to your problem (there are too many unknows for now). Try putting Debug.Log(wheel.localEulerAngles.ToString()); there and look how the value changes (you need to open a Console window in Unity to see the output).