Un cuaternión es una estructura matemática que representa rotaciones en el espacio 3D. Se define como q = {x, y, z, w}, donde:
- Los componentes x, y, z definen el eje de rotación.
- El componente w codifica el ángulo de rotación θ según θ = 2·arccos(w).
Los cuaterniones evitan el bloqueo de cardán (gimbal lock) y son más eficientes que las matrices de transformación. En Unity, son el método recomendado para manejar rotaciones.
Operaciones básicas con Quaternion
// Asignar rotación inicial (identidad)
transform.rotation = Quaternion.identity;
// Convertir ángulos de Euler a cuaternión
transform.rotation = Quaternion.Euler(30f, 45f, 0f);
// Rotar alrededor de un eje específico (eje Y, 90 grados)
transform.rotation = Quaternion.AngleAxis(90f, Vector3.up);
Interpolación suave de rotaciones
Lerp (lineal) – Útil para rotaciones pequeñas. La velocidad varía: más rápida al inicio y al final.
public Quaternion rotacionMeta;
void Update() {
float velocidad = Time.deltaTime * 5f;
transform.rotation = Quaternion.Lerp(transform.rotation, rotacionMeta, velocidad);
}
Slerp (esférica) – Mantiane velocidad angular constante, ideal para grandes ángulos.
transform.rotation = Quaternion.Slerp(rotacionActual, rotacionMeta, Time.deltaTime * 2f);
Orientación a un objetivo
// Hacer que el eje Z del objeto apunte hacia el objetivo
Vector3 direccion = objetivo.position - transform.position;
transform.rotation = Quaternion.LookRotation(direccion, Vector3.up);
// Rotación relativa entre dos vectores
Quaternion rotacionRelativa = Quaternion.FromToRotation(transform.forward, enemigo.position - transform.position);
Combinación de rotaciones
// Añadir rotación incremental sobre el eje Y
transform.rotation *= Quaternion.Euler(0f, 10f * Time.deltaTime, 0f);
Limitación de ángulos (ejemplo: cámara)
float cabeceoActual = transform.eulerAngles.x;
float cabeceoLimitado = Mathf.Clamp(cabeceoActual, -80f, 80f);
transform.rotation = Quaternion.Euler(cabeceoLimitado, transform.eulerAngles.y, 0f);
Rotar vectores con cuaterniones
Vector3 direccionMovimiento = transform.rotation * Vector3.forward;
Aplicaciones avanzadas
Rotación física (Rigidbody)
Rigidbody rb;
float velocidadRotacion = 10f;
void FixedUpdate() {
Quaternion deltaRot = Quaternion.Euler(0f, velocidadRotacion * Time.fixedDeltaTime, 0f);
rb.MoveRotation(rb.rotation * deltaRot);
}
Mezcla de animaciones
Quaternion rotacionMezclada = Quaternion.Lerp(
animator.GetBoneTransform(HumanBodyBones.Head).rotation,
rotacionCabezaObjetivo,
0.5f
);
Buenas prácticas y rendimiento
- Evitar conversiones frecuentes entre Euler y cuaternión. Trabaje siempre con
Quaternion.
// Incorrecto (cada frame convierte)
transform.eulerAngles += new Vector3(0, velocidad, 0);
// Correcto (usa multiplicación de cuaterniones)
transform.rotation *= Quaternion.Euler(0, velocidad, 0);
- Cachear rotaciones que se reutilicen.
private Quaternion rotacionInicial;
void Start() {
rotacionInicial = transform.rotation;
}
- Depuración visual: dibujar el eje forward.
void OnDrawGizmos() {
Gizmos.color = Color.red;
Gizmos.DrawRay(transform.position, transform.rotation * Vector3.forward * 2f);
}
Resumen de recomendaciones
- Use
Quaternionen lugar deeulerAnglespara cualquier lógica de rotación. - Para interpolación de grandes ángulos, use
Slerp; para pequeños,Lerp. - Combine rotaciones mediante multiplicación de cuaterniones (tenga en cuenta el orden).
- En bucles físicos, utilice
MoveRotationen vez de asignar directamente.