Las rotaciones en aplicaciones 3D se representan generalmente en una de dos maneras, ángulos de Quaternions o de Euler. Cada uno tiene sus propios usos y desventajas. Unity usa Quaternions internamente, pero muestra valores de los ángulos Euler equivalentes en el inspector para que sea fácil de editar.
Los ángulos de Euler tienen una representación más simple, que es tres valores de ángulo para X, Y y Z que se aplican secuencialmente. Para aplicar una rotación de Euler a un objeto en particular, cada valor de rotación se aplica a su vez, como una rotación alrededor de su eje correspondiente.
Los Quaternions se pueden usar para representar la orientación o rotación de un objeto. Esta representación interna consiste en cuatro números (referidos en Unity como x, y, z & w) sin embargo, estos números no representan ángulos o ejes y nunca es necesario acceder a ellos directamente. A menos que usted esté particularmente interesado en profundizar en las matemáticas de Quaternions, sólo necesita saber que un Quaternion representa una rotación en el espacio 3D y nunca lo hará normalmente Necesidad de conocer o modificar las propiedades x, y & z.
De la misma manera que un Vector puede representar una posición o una dirección (donde se mide la dirección desde el origen), un Quaternion puede representar una orientación o una rotación - donde la rotación se mide desde el “origen” o “Identity”. Es porque la rotación se mide de esta manera - de una orientación a otra - que un quaternion no puede representar una rotación más allá de 180 grados.
En Unity todas las rotaciones de Game Object se almacenan internamente como Quaternions, porque los beneficios superan las limitaciones.
En el Inspector de Transform, sin embargo, mostramos la rotación usando ángulos de Euler, porque esto es más fácil de entender y editar. Los nuevos valores introducidos en el inspector para la rotación de un objeto de juego se convierten “bajo el capó” en un nuevo valor de rotación Quaternion para el objeto.
Como efecto secundario, es posible que el inspector ingrese un valor de, por ejemplo, X: 0, Y: 365, Z: 0 para la rotación de un Game Object. Este es un valor que no es posible representar como un quaternion, por lo que al pulsar Reproducir verá que los valores de rotación del objeto cambian a X: 0, Y: 5, Z: 0 (o algo parecido). Esto se debe a que la rotación se convirtió en un Quaternion que no tiene el concepto de “Una rotación total de 360 grados más 5 grados”, y en cambio ha sido simplemente orientado de la misma manera que el resultado de la rotación.
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:
Sin embargo, a veces es deseable usar los ángulos de Euler en sus scripts. En este caso es importante tener en cuenta que usted debe mantener sus ángulos en las variables, y sólo usarlas para aplicarlas como ángulos de Euler a su rotación. Si bien es posible recuperar los ángulos de Euler de un quaternion, si recupera, modifica y vuelve a aplicar, surgirán problemas.
Aquí hay algunos ejemplos de errores comúnmente realizados usando un ejemplo hipotético de intentar girar un objeto alrededor del eje X a 10 grados por segundo. Esto es lo que debe evitar:
// 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 will not produce desired results
void Update () {
var rot = transform.rotation;
rot.x += Time.deltaTime * 10;
transform.rotation = rot;
}
// rotation scripting mistake #2
// the mistake here is that we are reading, modifying then writing the Euler
// values from a quaternion. Because these values calculated from a Quaternion,
// each new rotation may return very different Euler angles, which may suffer from gimbal lock.
void Update () {
var angles = transform.rotation.eulerAngles;
angles.x += Time.deltaTime * 10;
transform.rotation = Quaternion.Euler(angles);
}
Aquí hay un ejemplo del uso de Euler Angles en un script correctamente:
// rotation scripting with Euler angles correctly.
// here we store our Euler angle in a class variable, and only use it to
// apply it as a Euler angle, but we never rely on reading the Euler back.
float x;
void Update () {
x += Time.deltaTime * 10;
transform.rotation = Quaternion.Euler(x,0,0);
}
Muchos paquetes de creación en 3D y, de hecho, la propia ventana de animación de Unity, le permiten utilizar los ángulos de Euler para especificar las rotaciones durante una animación.
Estos valores de rotación pueden frecuentemente exceder el rango expresable por quaternions. Por ejemplo, si un objeto debe girar 720 grados en su lugar, esto podría ser representado por los ángulos de Euler X: 0, Y: 720, Z:0. Pero esto simplemente no es representable por un valor de Quaternion.
Dentro de la ventana de animación de Unity, hay opciones que le permiten especificar cómo debe interpolarse la rotación, utilizando la interpolación Quaternion o Euler. Al especificar la interpolación de Euler, le está diciendo a Unity que desea el rango completo de movimiento especificado por los ángulos. Con la rotación de Quaternion sin embargo, usted está diciendo que usted quiere simplemente que la rotación termine en una orientación particular, y la unidad utilizará la interpolación de Quaternion y girará a través de la distancia más corta para llegar allí. Consulte Uso de curvas de animación para obtener más información al respecto.
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.
Por ejemplo, imagine dos frames clave, 6 marcos separados, con valores para X como 0 en el primer frame clave y 270 para el segundo frame clave. Sin re-muestreo, una interpolación de quaternion entre estos dos frames clave giraría 90 grados en la dirección opuesta, porque esa es la forma más corta de pasar de la primera orientación a la segunda orientación. Sin embargo, al volver a muestrear y agregar un frame clave en cada frame, ahora sólo hay 45 grados entre frames clave para que la rotación funcione correctamente.
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.