Transfrom Flip Out, LocalEulerAngles.z (345-->15)

Hi there,
I am adjusting the z of a localEulerAngles. Generally I am shifting between 345 and 15 degrees. My issue is when I cross 0. At this point, the transform tends to flip about.

Any suggestions?

Have you read the answer to this question?

Sounds like you’re running into something called Gimbal Lock which is the reason Game Development uses Quaternions in the first place. To get around the problem try using Quaternion.Euler instead.

Gimbal lock would happen when you rotate one axis over another, not just about an axis, and once in the locked position any adjustment to that angle would result in no change… not “flipping about”.

In the same respect, OP doesn’t exactly describe what “flip about” even means. Or if they’re doing any other rotations around other axes. So they may actually be having gimbal lock and they just didn’t give us enough information. Of course, Quaternion.Euler doesn’t necessarily fix this since that’s just using euler angles. The ‘eulerAngles’ and ‘localEulerAngles’ properties are just wrappers around Quaternion.eulerAngles and Quaternion.Euler.

From decompiled ‘Transform’ source code:

    /// <summary>
    /// 
    /// <para>
    /// The rotation as Euler angles in degrees.
    /// </para>
    /// 
    /// </summary>
    public Vector3 eulerAngles
    {
      get
      {
        return this.rotation.eulerAngles;
      }
      set
      {
        this.rotation = Quaternion.Euler(value);
      }
    }

    /// <summary>
    /// 
    /// <para>
    /// The rotation as Euler angles in degrees relative to the parent transform's rotation.
    /// </para>
    /// 
    /// </summary>
    public Vector3 localEulerAngles
    {
      get
      {
        Vector3 vector3;
        this.INTERNAL_get_localEulerAngles(out vector3);
        return vector3;
      }
      set
      {
        this.INTERNAL_set_localEulerAngles(ref value);
      }
    }

(localEulerAngles does an internal call because it has to decompose its rotation from the global rotation through the parent tree, and it’s faster to do in C++ than in C#)

As for OP, still not sure what you mean by ‘flip about’, but it’s probably because you are using euler angles (just because it’s using euler angles, doesn’t mean gimbal lock, gimbal lock isn’t the only issue with euler angles). It does happen when you cross the 360 line which flips back to 0.

Instead of using eulerAngles to increment rotate around the z-axis, instead increment the quaternion:

transform.localRotation *= Quaternion.AngleAxis(30f, Vector3.forward); //rotate 30 degrees around the z axis

According to the docs Quaternion.Euler rotates in a specific order every time which is not the same as modifying Euler angles individually. If you had two of the values at 0 you effectively have an AngleAxis rotation around one of the major axes.

yes, if you did:

transform.localRotation *= Quaternion.Euler(0f, 0f, 30f);

But it’s not the using Quaternion.Euler that would do that, it’s the incrementing via Quaternion. I was making that distinction because you said it’s gimbal lock (which it isn’t) and that the answer is to use Quaternion.Euler, but didn’t explain in what manner to use Quaternion.Euler. The OP could easily have used it to SET the rotational value… which really is all ‘Transform.eulerAngles’ does in the first place.

Case in point, the source code I posted.

All Quaternion.Euler does is give you the amount of rotation from origin to that orientation. Which is useful. And can work just fine if you want to create a “n degrees around standard axis x,y, or z”. But it’s rigid and conforms to only those axes in that rotational order… I prefer the AngleAxis as it allows for pretty much any rotational direction in a human readable form… while being consistent. Otherwise when I’m rotating around the z axis, I’m using ‘.Euler’ but when I rotate around <1,1,1> I’m using ‘.AngleAxis’. Eh, why mix it all up like that.

Thanks all for the feedback.

In my case, since I am in total only rotating 30 degrees, 15 in one direction, 15 in the other. Since I am not needing to cover 360 + degrees, I have come up with a very simple solution.

Keeping my code to adjust the localEulerAngles, the parent transform I am rotating, I simply offset its rotation by 90 degrees at start. As such, I never cross the dreaded zero!!

Works like a charm.

Cheers!

1 Like