In the gif below, you can see that rotating on X moves all 3 axis including the X axis. It's possible it's rotating on the global X rather than local X (hard to tell). But Y looks more like it's rotating on global Z and Z is quite clearly rotating on local Z. What is going on? Why is there no consistency?
1 Answer
It's a common misconception that the three numbers in the Euler angle fields correspond in a simple 1:1 way with the three axes of the rotation gizmo on an object that we can see spatially in the editor. It's easy to disprove this though - once we've rotated the object on two axes, subsequent rotations using the editor gizmos will tend to change all three Euler angles at once:
That the three axes of the Euler angles happen to line up with the local axes / rotation gizmos when one or more axes are zero is something I'd recommend regarding as coincidence. In the general case, there's no simple relationship between Euler angles and the object's axes of rotation as shown & used in the editor or via Transform.Rotate calls.
So, what do the Euler angles represent? They specify a sequence of rotations, applied in the following order:
Rotation by
z
degrees about world Z+
(This is why it looks like the z parameter rotates around local Z+: since it's applied first, the local and world z are identical at first.)Rotation
x
degrees about world X+
(If ourz
rotation was zero, this is the same as rotating about local X+. If not, then the rotation we applied in the previous step affects the relationship between the object and the x rotation axis, and so on down the chain...)Rotation by
y
degrees about world Y+
(Since this one comes last, it's the "most global" of the three, which is why it tends to align with world Y in the final transformation - unless we're inside a rotated parent object which then turns this axis somewhere else...)Parent's rotations
(again in the order Z-X-Y, all the way up the transform hierarchy)
Each of these three fields is applied all at once as a total when its turn in the sequence comes. Since rotations are not commutative, that means you get a different result than if you saved some of the rotation to apply "on top" as an increment after the rest. That's why it doesn't behave in a very intuitive way once you've already rotated an object.
If you have an object rotated at (-54, 38, -25) in Euler angles, and then you change the x
value to -79, the Euler angles don't "remember" that the first -54 degrees were applied first, and then apply the remaining 25 degrees relative to those resulting axes. The Euler angles are just numbers. So they give you the result of rotating -25 on Z, then -79 on X, then 38 on Y.
Because any changes to the numbers get folded-in this way, Euler angles can behave in profoundly non-intuitive ways if you're trying to manipulate them one angle at a time. They're an effective way of storing / printing a rotation in a way that's concise and human-readable, but not a good way of modifying or computing a rotation.
For those manipulating orientations, you'll more often want to use the editor gizmos (which represent incremental rotation about a specific axis), Transform.Rotate, quaternion composition, or constructing your desired orientation from forward & up basis vectors.
-
\$\begingroup\$ Sorry, I'm not quite following how this applies to my situation. You can see both sets of local and global axes and I'm only rotating on one axis at a time. This would make sense to me if I were trying to rotate on 2 at the same time and getting something I didn't expect because it did one axis before the other, but that's not what I'm doing here. Am I missing something? \$\endgroup\$ Commented Aug 12, 2018 at 20:49
-
\$\begingroup\$ You are indeed. Note that in your example, all three of your Euler angle rotation fields have a non-zero entry. That means you're not rotating on one axis at a time when you vary one of the numbers. In the frames where you vary the x value between -25 to -79 or so, you're not seeing the effect of rotating 54 degrees on one axis. You're seeing the effect of first rotating 38.7° about the world Z+ axis, then rotating the result -25 – -79° about the world X+ axis, then rotating that result -27° about the world Y+ axis. Euler angles always represent a sequence. \$\endgroup\$– DMGregory ♦Commented Aug 12, 2018 at 20:57
-
\$\begingroup\$ The Euler angles have no way to remember "Oh, -54.2° degrees of this rotation on X were already applied earlier, and the remaining -19 or so should be applied relative to wherever the X axis was after that setup" — it's just a simple total. And those totals are always applied as a whole in the order Z-X-Y. So it's misleading to think of applying incremental rotations on the Euler angle numbers directly. You're usually better served using the rotation gizmos in the editor, or quaternion composition in scripts. The model Euler angles present is not one that maps well to our intuition. \$\endgroup\$– DMGregory ♦Commented Aug 12, 2018 at 21:01
-
\$\begingroup\$ Interesting... I think I might understand. So each axis is again individually considered when I rotate on just one axis in the inspector? And the local axes shown on the screen reflect the end position but cannot be used to determine what incremental changes will do? What about transform.Rotate(1, 0, 0)? Will that incrementally rotate precisely on the local X axis as seen in the image? \$\endgroup\$ Commented Aug 12, 2018 at 21:08
-
1\$\begingroup\$ Yes. Euler angles are just a definition of where something is now. They make no promises about the future. They axes / rotation gizmos you see in the inspector, and rotations you apply through Transform.Rotate, have no relationship to the three numbers in the Euler angles fields (it's easy to arrange an object so that rotating in just one gizmo axis changes all three Euler angle numbers). Basically, think of Euler angles as a way of storing/printing a rotation, not a way of working with it. \$\endgroup\$– DMGregory ♦Commented Aug 12, 2018 at 21:20