1
\$\begingroup\$

I've read somewhere that a Quaternion in Unity ranges between [-1,1] values. I mean the individual XYZW values. Ex: new Quaternion(.1f,.2f,-.3f,-.4f)

Is this true?

More clearly: I know they take float values therefore the theoretical limit is floating point value limitations, I'm asking the real rotation results. For instance when I look up Quaternion values while rotating a GameObject it is usually in the [-1,1] limits. But I'm not sure if that's my case or not.

\$\endgroup\$
4
  • 2
    \$\begingroup\$ What is the issue that you're having? \$\endgroup\$
    – Vaillancourt
    Commented Mar 9, 2020 at 15:26
  • \$\begingroup\$ I have a Quaternion value that doesn't go beyond .7 it reverts back to .6 and decreases when the rotation continues in that direction. Trying to figure out why it happens. \$\endgroup\$ Commented Mar 9, 2020 at 15:51
  • 1
    \$\begingroup\$ That suggests that your rotation is no more than 90 degrees from neutral. sin(90/2) = cos(90/2) = 1/sqrt(2) = 0.707... If you're never turning your object around so much that it ends up upside-down, or looking backwards along the negative z axis, then we'd expect your quaternion components to stay in this range. \$\endgroup\$
    – DMGregory
    Commented Mar 9, 2020 at 16:42
  • \$\begingroup\$ Problem occured from parent's rotation pushing the child out of the bounds DMG said. It's not something anyone other than me would encounter(I'm dumb). I solved it by re-exporting the entire mesh(1 parent 3 child) with some settings, fixing the orientation of the children, which was broken beyond repair. I don't know why the orientations broke in the initial export but it was hell. Still, learned a lot on Quats. That's one problem scratched. \$\endgroup\$ Commented Mar 9, 2020 at 19:29

2 Answers 2

3
\$\begingroup\$

Rotations and orientations in Unity are represented by unit quaternions.

That means a quaternion \$(w, x, y, z)\$ where:

$$w^2 + x^2 + y^2 + z^2 = 1$$

You can see this means each component is in the range from -1 to 1, and if any one component is near the edge of that range, the rest of the components will be closer to zero so the sum of their squares doesn't exceed 1.

If you can visualize 4 dimensions, unit quaternions are points on the surface of a 4-dimensional sphere. If your math ends up producing a quaternion outside this range, you can normalize it to snap it back onto the sphere. (Quaternion.Lerp() does this to get a quick & dirty blend between quaternions that stays on the unit sphere, more cheaply than a true uniform Slerp)

Usually the w component will be greater than 0. This corresponds to the shortest rotation from the initial orientation to the destination orientation. If you negate the whole quarternion so that w is negative (and the axis is reversed), you get the rotation that goes "the long way around" to get to the same output, say turning 270° to the left instead of 90° to the right. If the w component is exactly zero, that's a 180° rotation, so it's the same distance in either direction.

Most quaternion methods will give you a w greater than or equal to zero by default, but if you do a bunch of math to transform quaternions you can sometimes end up with a negative w. If you're using the quarternion as an orientation rather than a relative rotation to travel through, it won't make a difference since you still end up in the same place. But if you're lerping / slerping / rotateTowards-ing then keeping the w positive can ensure you get the shortest travel consistently.


As Almo says, you should almost never need to inspect or manipulate a quaternion's individual components directly. But if you find a need to do so, it can help to understand how they're calculated:

  • (x, y, z) = axis of rotation (unit vector) times the sine of half the angle of rotation

  • w = cosine of half the angle of rotation

So if a quaternion \$q\$ is representing a rotation about axis \$ \vec a \$ by an angle \$\Theta\$ then...

$$q_w = \cos \frac \Theta 2\\ q_x = a_x \cdot \sin \frac \Theta 2\\ q_y = a_y \cdot \sin \frac \Theta 2\\ q_z = a_z \cdot \sin \frac \Theta 2 $$

So an identity rotation (angle = 0) is just (w = 1, x = 0, y = 0, z = 0)

A rotation of 180 degrees around the y axis is (0, 0, 1, 0)

And a rotation halfway between these two extremes — 90 degrees around the y axis — is \$( \frac 1 {\sqrt 2}, 0, \frac 1 {\sqrt 2}, 0)\$

Something you'll notice here is that to invert a quaternion - to make a quaternion that represents the opposite rotation and "undoes" the original rotation - all you have to do is negate the rotation axis components x, y, z, while keeping w unchanged. That makes Quaternion.Inverse() dirt cheap compared to inverting an arbitrary matrix - maybe even cheaper than transposing an orthonormal rotation matrix, since you have to touch just three variables, not six. So don't be afraid to invert quaternions on demand. ;)

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Better answer than mine. Explains why we observe Quaterions in Unity not to have coefficient outside the range [-1, 1]. \$\endgroup\$
    – Almo
    Commented Mar 9, 2020 at 15:35
  • \$\begingroup\$ Also I think my source was this for those wondering: answers.unity.com/questions/645903/…. \$\endgroup\$ Commented Mar 9, 2020 at 15:54
1
\$\begingroup\$

I can't find anything in either the Unity docs or Quaternions themselves that would indicate the coefficients are limited in range. They are real numbers, but that appears to be the only restriction.

Quaternions are generally represented in the form:

a + bi + cj + dk

where a, b, c, and d are real numbers, and i, j, and k are the fundamental quaternion units.

The Unity docs also say that you should never have to mess with a Quaternion's coefficients unless you really know what you're doing.

https://docs.unity3d.com/ScriptReference/Quaternion.html

https://en.wikipedia.org/wiki/Quaternion

\$\endgroup\$
2
  • 2
    \$\begingroup\$ "The Unity docs also say that you should never have to mess with a Quaternion's coefficients" this is such an important point. I see a lot of devs getting snared trying to break down a quaternion into components and do if checks or math to manipulate one component at a time, and it's almost never the correct or simplest/clearest way to get the behaviour they want. Unity has great convenience methods to work with quaternions in more intuitive ways - like composing quaternions to chain them together, forming quaternions from basis vectors or rotation axes, or measuring the angle between them. \$\endgroup\$
    – DMGregory
    Commented Mar 9, 2020 at 16:39
  • 2
    \$\begingroup\$ One caveat to "I can't find anything...in the Unity docs": the doc page does mention "Note that Unity expects Quaternions to be normalized," and the Wikipedia article on quaternions and spatial rotation does mention the isomorphism is with "unit quaternions" - but I'll agree this terminology takes a little unpacking to recognize this limits the components to [-1, 1] \$\endgroup\$
    – DMGregory
    Commented Mar 9, 2020 at 16:52

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .