Rotar en 3D no es sumar grados#
En 2D rotar es un número (grados en Z). En 3D es engañoso: rotar sobre tres ejes no es conmutativo (girar X y luego Y ≠ girar Y y luego X) y aparece el temido gimbal lock. Por eso Unity guarda las rotaciones internamente como Quaternions, no como ángulos.
El gimbal lock#
Con ángulos de Euler (X, Y, Z), en ciertas orientaciones dos ejes se alinean y pierdes un grado de libertad: la rotación "se atasca". Es un problema real que sufre cualquier cámara o nave controlada solo con Euler.
Un Quaternion representa una orientación con cuatro componentes (x, y, z, w) sin sufrir gimbal lock y permitiendo interpolar suave entre dos rotaciones. No se entienden "mirándolos" (no son grados), pero no hace falta: usas los métodos de ayuda de Unity y ya.
La regla de oro#
Nunca hagas transform.rotation.x += 1 (rompe el Quaternion) ni acumules en transform.eulerAngles (puede dar saltos por el gimbal lock). Usa siempre los helpers: Quaternion.Euler, LookRotation, Slerp, RotateTowards, AngleAxis o transform.Rotate.
Las tareas reales#
Fijar una rotación por grados#
// Grados legibles -> Quaternion, la forma correcta de "poner" una rotación
transform.rotation = Quaternion.Euler(0f, 90f, 0f);Girar sobre un eje cada fotograma#
// Rota 90°/segundo sobre Y (independiente de FPS con deltaTime)
transform.Rotate(0f, 90f * Time.deltaTime, 0f);Mirar hacia un objetivo#
Vector3 dir = objetivo.position - transform.position;
Quaternion mirar = Quaternion.LookRotation(dir); // orientación que "mira" a dir
transform.rotation = mirar;Girar SUAVE hacia el objetivo#
Casi nunca quieres el giro instantáneo, sino uno progresivo:
void Update()
{
Vector3 dir = objetivo.position - transform.position;
Quaternion objetivoRot = Quaternion.LookRotation(dir);
// Slerp: interpola suave entre la rotación actual y la deseada
transform.rotation = Quaternion.Slerp(transform.rotation, objetivoRot, 5f * Time.deltaTime);
// Alternativa a velocidad constante (grados/seg): RotateTowards
// transform.rotation = Quaternion.RotateTowards(transform.rotation, objetivoRot, 180f * Time.deltaTime);
}Slerp con t = velocidad * deltaTime da un giro que frena al acercarse (suave, tipo cámara). RotateTowards gira a velocidad constante en grados/segundo y no se pasa del objetivo (ideal para torretas o naves). Elige según la sensación que busques.
Combinar y deshacer rotaciones#
Quaternion a = Quaternion.Euler(0, 45, 0);
Quaternion combinada = a * Quaternion.Euler(0, 0, 30); // multiplicar = aplicar una tras otra (¡el orden importa!)
Quaternion inversa = Quaternion.Inverse(a); // deshacer una rotaciónEspacio local vs mundo#
transform.rotation es la rotación en el mundo; transform.localRotation, relativa al padre. Y transform.Rotate(..., Space.Self/World) elige sobre qué ejes giras. Confundirlos es causa típica de "gira raro". Ver Transform.
Errores frecuentes#
- Sumar a
transform.eulerAngleso tocarrotation.xa mano (saltos, gimbal lock, Quaternion roto). - Usar
LookRotationcon una dirección de longitud 0 (objetivo y objeto en el mismo punto) → warning y rotación indefinida. - Olvidar
Time.deltaTimeenRotate/Slerp(velocidad dependiente de FPS). - Mezclar espacio local y mundo sin querer.
- Interpolar rotaciones con
Lerpde vectores de Euler en vez deSlerpde Quaternions (da giros feos).
Ponte a prueba#
Resumen#
Rotar en 3D es traicionero (no conmuta, hay gimbal lock), por eso Unity usa Quaternions. No los toques a mano ni sumes eulerAngles: usa los helpers. Fija con Quaternion.Euler, gira sobre un eje con transform.Rotate, mira a algo con LookRotation, y hazlo suave con Slerp (frena al llegar) o RotateTowards (velocidad constante), siempre con Time.deltaTime. Y ten claro el espacio local vs mundo del Transform.