Rotations in 3D applications are usually represented in one of two ways: Quaternions or Euler angles. Each has its own uses and drawbacks. Unity uses Quaternions internally, but shows values of the equivalent Euler angles in the Inspector to make it easy for you to edit.
Euler angles are represented by three angle values for X, Y and Z that are applied sequentially. To apply a Euler rotation to a particular GameObject, each rotation value is applied in turn, as a rotation around its corresponding axis.
Quaternions can be used to represent the orientation or rotation of a GameObject. This representation internally consists of four numbers (referenced in Unity as x, y, z & w) however these numbers don’t represent angles or axes and you never normally need to access them directly. Unless you are particularly interested in delving into the mathematics of Quaternions, you only really need to know that a Quaternion represents a rotation in 3D space and you never normally need to know or modify the x, y & z properties.
In the same way that a Vector can represent either a position or a direction (where the direction is measured from the origin), a Quaternion can represent either an orientation or a rotation - where the rotation is measured from the rotational “origin” or “Identity”. It is because the rotation is measured in this way - from one orientation to another - that a quaternion can’t represent a rotation beyond 180 degrees.
Unity stores all GameObject rotations internally as Quaternions, because the benefits outweigh the limitations.
The Transform Inspector displays the rotation using Euler angles, because this is easier to understand and edit. Unity converts new values into the Inspector for the rotation of a GameObject into a new Quaternion rotation value for the GameObject.
As a side-effect, it is possible in the Inspector to enter a value of, say, X: 0, Y: 365, Z: 0 for a GameObject’s rotation. This value is not possible to represent as a quaternion, so when you enter Play mode, the GameObject’s rotation values change to X: 0, Y: 5, Z: 0. This is because Unity converts rotation to a Quaternion which does not have the concept of a full 360-degree rotation plus 5 degrees, and instead is set to orient the same way as the result of the rotation.
Cuando se trata de manejar rotaciones en sus scripts, debe utilizar la clase Quaternion y sus funciones para crear y modificar valores de rotación. Hay algunas situaciones en las que es válido usar ángulos de Euler, pero debes tener en cuenta: - Debe utilizar las funciones de la clase Quaternion que se ocupan de los ángulos de Euler - Recuperar, modificar y volver a aplicar los valores de Euler desde una rotación puede causar efectos secundarios no intencionales.
La clase Quaternion de Unity tiene una serie de funciones que le permiten crear y manipular rotaciones sin necesidad de usar ángulos de Euler en absoluto. Por ejemplo:
Creando:
Manipulando:
However sometimes it’s desirable to use Euler angles in your scripts. In this case it’s important to note that you must keep your angles in variables, and only use them to apply them as Euler angles to your rotation. While it’s possible to retrieve Euler angles from a quaternion, if you retrieve, modify and re-apply, problems are likely to arise.
Here are some examples of mistakes commonly made using a hypothetical example of trying to rotate a GameObject around the X axis at 10 degrees per second. This is what you should avoid:
// rotation scripting mistake #1
// the mistake here is that we are modifying the x value of a quaternion
// this value does not represent an angle, and does not produce desired results
void Update ()
{
var rot = transform.rotation;
rot.x += Time.deltaTime * 10;
transform.rotation = rot;
}
// rotation scripting mistake #2
// Read, modify, then write the Euler values from a Quaternion.
// Because these values are calculated from a Quaternion,
// each new rotation might return very different Euler angles, which might suffer from gimbal lock.
void Update ()
{
var angles = transform.rotation.eulerAngles;
angles.x += Time.deltaTime * 10;
transform.rotation = Quaternion.Euler(angles);
}
And here is an example of using Euler angles in script correctly:
// Rotation scripting with Euler angles correctly.
// Store the Euler angle in a class variable, and only use it to
// apply it as a Euler angle, but never rely on reading the Euler back.
float x;
void Update ()
{
x += Time.deltaTime * 10;
transform.rotation = Quaternion.Euler(x,0,0);
}
See documentation on Quaternion.Euler for more details.
Many 3D authoring packages, and Unity’s own internal Animation window, allow you to use Euler angles to specify rotations during an animation.
These rotations values can frequently exceed ranges expressable by quaternions. For example, if a GameObject rotates 720 degrees, this could be represented by Euler angles X: 0, Y: 720, Z:0. But this is not representable by a Quaternion value.
Within Unity’s own animation window, there are options which allow you to specify how the rotation should be interpolated - using Quaternion or Euler interpolation. By specifying Euler interpolation you are telling Unity that you want the full range of motion specified by the angles. With Quaternion rotation however, you are saying you simply want the rotation to end at a particular orientation, and Unity uses Quaternion interpolation and rotate across the shortest distance to get there. See Using Animation Curves for more information on this.
Al importar animaciones de fuentes externas, estos archivos normalmente contienen animación de frames clave rotativos en formato Euler. El comportamiento predeterminado de Unity es volver a muestrear estas animaciones y generar un nuevo frame clave de Quaternion para cada frame de la animación, en un intento de evitar situaciones en las que la rotación entre fotogramas clave pueda exceder el rango válido de Quaternion.
For example, imagine two keyframes, 6 frames apart, with values for X as 0 on the first keyframe and 270 on the second keyframe. Without resampling, a quaternion interpolation between these two keyframes would rotate 90 degrees in the opposite direction, because that is the shortest way to get from the first orientation to the second orientation. However by resampling and adding a keyframe on every frame, there are now only 45 degrees between keyframes so the rotation works correctly.
Todavía hay algunas situaciones en las que - incluso con el remuestreo - la representación de quaternion de la animación importada puede no coincidir con el original lo suficientemente estrechamente, por eso, en Unity 5.3 y en adelante existe la opción de desactivar el resampling (remuestreo) de animación, Utilice los frames clave de la animación original de Euler en tiempo de ejecución. Para obtener más información, consulte Importación de animación de Rotaciones de Curvas Euler.