Jump to content
UnitySpain

Aceptamos donaciones vía Paypal.

UnitySpain.com es un servicio gratuito, pero mantener la Comunidad conlleva una serie de gastos.

Fondo Anual Unityspain: Donados 15,00€ de 150,00€

  • Servidor: Dominio.com y Hosting Web
  • Mantenimiento de los Foros
  • Contenido y Servicios Extras
  • Mantenimiento para Redes Sociales
Sign in to follow this  
Jhonatan00_00

ANSWERED Ejes de rotación cambiados (SOLUCIONADO)

Recommended Posts

Buenas tardes, tengo un problemilla un tanto extraño que no se solucionar y es que mi personaje tiene los ejes correctamente alineados y rota bien, pero su cabeza los tiene invertidos (no se por que) y no puedo hacer que mire hacia un punto en concreto, un objeto, etc porque al usar LooKAt o Quaternion.LookRotation los ejes hacen que rote con la cabeza ladeada y de formas muy extrañas.

He probado a solucionar el problema corrigiendo los ejes desde el programa de modelado 3D, pero es imposible porque al editar su pivote la cabeza se dobla y las animaciones se estropean. También he intentado darle las coordenadas del eje Y del Quaternion.LookRotation al eje X por script (porque es el eje que la cabeza me usa como eje Y y manualmente rota bien tocándolo desde su ventana de transform), pero sigue haciendo cosas raras.

- ¿Alguna forma de resetear o reajustar el pivote de un objeto en Unity o por script para que funcione correctamente?.

Un saludo.

Edited by Jhonatan00_00
Procura añadir un Tag

Share this post


Link to post
Share on other sites

hola

puedes usar el transform.LookAt y luego rotarlo manualmene para corregir con transform.Rotate(x,y,z)

por ejemplo pongamos que al rotarlo con LookAt la cabeza queda ladeada 90 en el eje Z pues luego le pones un Rotate(0, 0, -90) y solucionado.... o si queda mirando hacia arriba le pones un Rotate(90, 0, 0)... (pero despues del LookAt)

espero que te sirva.

sino, hay otras formas de hacerlo, puedes poner un objeto vacio (empty gameobject) dentro de la cabeza y que ese si este orientado correctamente, calculas el vector3 "normalizado" desde ese objeto al punto  donde debe mirar, y con vector3.dot entre ese vector y los vectores forward y right puedes calcular el seno y coseno de los angulo Y que forma, ...y con el vector y forward y up puedes calcular seno y coseno del angulo X... sabiendo los senos y cosenos puedes usar Mathf.ATan2 para saber el angulo y luego los usas en el eje apropiado con Rotate, rotando porejemplo el eje "Y" con el angulo "X" y el eje "Z" con el angulo "Y"... o lo que sea...

y aun hay mas maneras de solucionarlo..

porejemplo rotas la cabeza con LookAt, guardas los valores del transform.eulerAngles en un vector3 "angulosCabeza" y luego intercambias los valores de X por Y o lo que sea... osea pones los eulerAngles en otro orden... en vez de x,y,z luego le metes los valores en otro orden... z,x,y o lo que sea... aunque creo que hacer esto fallara porque primero tendrias que hayar el angulo entre el cuerpo y la cabeza (anguloY cabeza menos anguloY cuerpo) y eso son los valores que luego tendrias que intercambiar... 

y seguro que hay mas formas...

si no te funciona ninguna de estas puedo pensar otra... o si no logras hacer una de las que te he puesto (ya que lo he explicado a lo rapido) puedo intentar explicarlo mejor... o tambien si quieres te pongo ejemplos con codigo

Edited by Igor

Share this post


Link to post
Share on other sites

Gracias Igor, que fáciles parecen las cosas cuando preguntas en este foro, ya está solucionado. Simplemente he añadido después del LookAt como ha dicho, transform.Rotate (0,-90,-90) y ahora rota bien. Pensaba que este problema no tendría solución porque buscando en google nadie sabia solucionarlo, solo una persona que creó un script para solucionar algo parecido, que cuando exportases de Blender a Unity los objetos no tuviesen los ejes de rotación mal y no creo que me funcionase a mi porque mi personaje si tiene los ejes bien, era solo el de la cabeza el que estaba mal.

Un saludo y gracias!!. :6_smile::91_thumbsup:

Share this post


Link to post
Share on other sites

En mi caso recientemente me di cuenta de que durante gran parte de mi vida (un 99.99998%) estuve usando blender mal (y exportando mal también). Resulta que estaba usando el "frente" a la vista que se logra apretando el numpad "3" (para los que lo usen van a entender), osea el plano YZ. En realidad el frente se considera a la vista lograda con "1" (no "3"), es decir, el plano XY (X a derecha, Y hacia adelante Z hacia arriba ---> Right handed). Que pasaba? que siempre debía de rotar 90 grados el modelo.

Blender usa coordenadas "Right Handed" vs las "Left handed" de Unity, de acá la necesidad de transformar los ejes. En las opciones de exportación podés retransformar los ejes, yo estaba asumiendo que el problema era el otro (el sistema de coordenadas) cuando en realidad era que yo mismo estaba rotando el modelo en blender.

Con respecto a las animaciones estropeadas, si tenés en cuenta bien los ejes podés retransformar todo a Unity sin perder todo (Seguramente podés lograrlo desde el mismo Blender modificando los transform o algo por el estilo).

En fin, no se si está relacionado a tu problema pero lo menciono ya que después de tanto tiempo se me dió por mirar los tres pequeños ejes que aparecían en el visor :6_smile:.

Share this post


Link to post
Share on other sites

Buenas tardes Lightbug, errores de ese tipo hemos cometido todos alguna vez pero no es el caso. Mi personaje tiene su eje de rotación correctamente, el problema me lo causa el eje de rotación que ya tiene por defecto el cuello y la cabeza. Los bones de la cabeza y el cuello están alineados por defecto de una forma especifica para que animar al personaje sea mas sencillo (supongo) y no se pueden cambiar.

He "solucionado" el problema usando LookAt y transform.Rotate (0,-90,-90), pero pongo "solucionado" entre comillas, porque aunque la cabeza rota hacia donde tiene que hacerlo, lo hace instantáneamente y si uso Quaternion.slerp con transform.Rotate (0,-90,-90) para corregir el problema, lo que me hace es mirar hacia la dirección que quiero pero con la cabeza un poco ladelada, no me lo corrige 100%.

Estoy probando mil cosas como cambiar el orden de los ejes del resultado que me da el Quaternion.LookRotation, pero nada me funciona... así que seguiré probando cosas.

Un saludo.

Edited by Jhonatan00_00

Share this post


Link to post
Share on other sites

nose si mira siempre a un sitio o es en determinados momentos o como lo usas... 

pero puedes hacer algo asi....

para que rote suave tienes que tener una variable private Quaternion oldRot; en el script.

y pones algo asi:

transform.LookAt(sitio)

transform.Rotate(0,-90,-90)

cabeza.rotation = Quaternion.Lerp(oldRot, cabeza.rotation, 0.1f);

oldRot = cabeza.rotation;

no se si eso ira bien porque no se como va tu script... si pones el codigo podre ayudarte mejor

igual hay que alterar el orden... o hacerlo diferente...

pero poderse se puede, todo se puede hacer en programacion

Share this post


Link to post
Share on other sites

Buenas noches, el script de la cabeza no tiene aún  prácticamente nada programado porque es muy simple y debería de funcionar sin mas... He creado un script que tiene un transform publico donde meto el objeto que quiero que mire, después hallo la dirección de ese objeto restando la posición de la cabeza a la del objeto y uso esa resta en una variable para usarla con Quaternion.LookRotation. Después con Quaternion.Slerp debería de rotar bien, pero no lo hace. El script que he creado es básicamente esto:

using UnityEngine;
using System.Collections;

public class Cabeza : MonoBehaviour {

    public Transform Objeto;
    private Vector3 Direccion_Cabeza;
    private Quaternion Rotacion;

    void LateUpdate () {

        Direccion_Cabeza = Objeto.transform.position - transform.position;
        Rotacion = Quaternion.LookRotation (Direccion_Cabeza);

        if (Input.GetAxis("Horizontal") != 0 || Input.GetAxis("Vertical") !=0) {
            transform.rotation = Quaternion.Slerp (transform.rotation, Rotacion, 10 * Time.deltaTime);
        }
    }
}

Lo que si he observado es que con Quaternion.slerp aunque esté usando una suavidad de rotación de 1* Time.deltaTime la cabeza mira directamente al objeto (con la cabeza ladeada) y no lo hace como una transición. ¿Por que?, no entiendo nada... :37_disappointed:

Me voy a cenar que ya es muy tarde y mañana cuando tenga un rato sigo. Saludos!!.

Edited by pioj
Por favor, usa el <> o el "quote" para pegar código.

Share this post


Link to post
Share on other sites

Buenos días, estoy haciendo pruebas y he observado que cuando uso LookAt y después corrijo la rotación con transform.Rotate (0, -90, -90) la cabeza se posiciona correctamente, pero en cambio si lo que uso es Quaternion.Slerp o Lerp, aunque intente corregir después la rotación con Rotacion.y = Rotacion.y - 90 y Rotacion.z = Rotacion.z - 90, la rotación me cambia a cuando he usado LookAt y la cabeza sigue rotando en direcciones raras.

Algo tan simple y que se vuelva así de complejo por no poder editar el pivote de la cabeza desde el programa 3D. :61_sob:

EDITO -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Ya se por que con Quaternion.Slerp no me funcionaba lo de corregir los ángulos, era simplemente porque el  transform.Rotate (0,-90,-90) lo ponía antes de sacar la resta entre vectores, pensando que así me sacaría bien el cálculo y al pensarlo me he dado cuenta de que el cálculo de la resta para saber hacia donde mirar se basa en posiciones, no en rotaciones y que lo que hacemos con transform.Rotate (0,-90,-90) es corregir lo que está mal en la rotación después, por lo que hay que ponerlo justo después del Quaternion.Slerp.

No obstante sigo sin entender por que usando Slerp la rotación la hace instantánea... no tiene sentido... Si lo descubro diré algo.

Por otra parte perdonadme si digo cosas muy raras o contradictorias en mis mensajes o si en uno hablo de usar un método y en el siguiente os lio hablando de otro diferente, pero es que me pongo a probar muchas cosas hasta que doy con la solución. De todas formas he marcado la respuesta donde está la solución, lo único que estoy tratando de hacer ahora es que rote pero suavemente.

Saludos.

Edited by Jhonatan00_00

Share this post


Link to post
Share on other sites

Buenas noches, el problema sigue siendo que la animación del Animator interfiere con el movimiento de la cabeza por script y me he dado cuenta porque si desactivo el Animator funciona. Le he dado un montón de vueltas y la mejor manera de solucionar el tema de los ejes para poder usar Quaternion.Slerp y que el movimiento sea suave es la siguiente:

using UnityEngine;
using System.Collections;

public class Cabeza : MonoBehaviour {

	public Transform Objeto;
	private Vector3 Direccion_Cabeza;
	private Quaternion Rotacion;
	private Quaternion Correccion;

	void LateUpdate () {

		Direccion_Cabeza = Objeto.transform.position - transform.position;
		Rotacion = Quaternion.LookRotation (Direccion_Cabeza);
		Correccion = Quaternion.Euler (transform.rotation.x ,transform.rotation.y -90,transform.rotation.z -90);

		if (Input.GetAxis("Horizontal") != 0 || Input.GetAxis("Vertical") !=0) {
			transform.rotation = Quaternion.Lerp (transform.rotation, Rotacion * Correccion, 5 * Time.deltaTime);
		}
	
	}
}

Y simplemente haciendo que el transform "Objeto" se recoloque en la posición del objeto que queremos que mire conseguiremos nuestro objetivo. Pero en cuanto activo el Animator las fuerzas del Animator y el Script se oponen y la cabeza no gira correctamente. 

- ¿Nadie ha hecho esto de que su personaje mire a un objeto antes?, es que no hay información por ningún sitio. :4_joy:

- ¿Puedo desactivar por script las animaciones del Animator pero solo de la cabeza en el momento que yo lo necesite?.

Saludos.

Edited by Jhonatan00_00

Share this post


Link to post
Share on other sites

para solucionarlo bien bien tendria que tener mucha mas informacion....

cual es el eje que mira hacia adelante en la cabeza.... porque si dices que estan mal los ejes signnifica que el Z no apunta hacia adelante... y entonces seguro que el Y no apunta hacia arriba y el X no apunta hacia la derecha....

porque lo suyo seria hacerlo usando los ejes y calcular cuanto tiene que rotar con respecto a como esta rotada "dentro" de la animacion... porque la animacion supongo que movera un poco la cabeza (suavemente)..

 lo suyo seria calcular el angulo usando los vectores de direccion de la cabeza... usando Vector3.Dot para obtener seno y coseno del angulo que forma la cabeza respecto al vector al que llamas "Direccion_Cabeza"(*)... y luego usar Mathf.ATan2 para hayar el angulo que debes girar.

si me das los ejes, si me dices hacia donde apuntan los ejes x,y,z de la cabeza puedo intentar hacertelo, ...pero al final no se si funcionara bien... lo suyo seria que pudiera acceder a tu proyecto y asi te lo podria "arreglar" en un momento... unas unityCloud? tienes el proyecto en la "nube" de unity? si quieres te paso mi correo para que me des acceso (momentaneo) a tu proyecto y le hecho un ojo... aunque este finde me pilla un poco mal... estare viernes, sabado y domingo fuera... pero el lunes te lo puedo mirar si quieres

 

(*) las variables deberian comenzar con minusculas ("direccion_Cabeza") y las "classes" y funciones en Mayuscula.

Share this post


Link to post
Share on other sites

Buenos días Igor, el tema de la rotación ya está solucionado y también que rote suavemente, solo necesito saber como desactivar-activar la animación del Animator de una parte del cuerpo por script para que no se mezcle la animacion del Animator con la del Script.

Estoy viendo por Internet que es algo muy común y que existen comandos para hacer lo que necesito, porque a veces uno necesita que su personaje saque un arma y siga apuntando a un enemigo mientras corre por ejemplo. En el momento en el que saca el arma, la animación de ese brazo se desactiva y lo que actúa es la animación por script, pero usan un comando para desactivar el Animator, ¿cual es?. Aún no tengo ni idea :7_sweat_smile:

Saludos.

Share this post


Link to post
Share on other sites
9 hours ago, Jhonatan00_00 said:

Buenos días Igor, el tema de la rotación ya está solucionado y también que rote suavemente, solo necesito saber como desactivar-activar la animación del Animator de una parte del cuerpo por script para que no se mezcle la animacion del Animator con la del Script.

Estoy viendo por Internet que es algo muy común y que existen comandos para hacer lo que necesito, porque a veces uno necesita que su personaje saque un arma y siga apuntando a un enemigo mientras corre por ejemplo. En el momento en el que saca el arma, la animación de ese brazo se desactiva y lo que actúa es la animación por script, pero usan un comando para desactivar el Animator, ¿cual es?. Aún no tengo ni idea :7_sweat_smile:

Saludos.

En el animator existen Mask Avatar que son justamente para habilitar o deshabilitar el link de los huesos con la malla. 
https://docs.unity3d.com/es/530/Manual/class-AvatarMask.html

Todo esto se llama IK (Inverse Kinematics) es un tema complejo a nivel matemático, pero Unity ofrece módulos que solucionan parte del problema.

Recuerda que puedes utilizar OnAnimatorIK desde un componente que se encuentre en el mismo GameObject que AnimatorController para sobre escribir y crear tus comportamientos IK.

 animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, leftFootPositionWeight);
 animator.SetIKRotationWeight(AvatarIKGoal.LeftFoot, leftFootRotationWeight);
 animator.SetIKPosition(AvatarIKGoal.LeftFoot, leftFootObj.position);
 animator.SetIKRotation(AvatarIKGoal.LeftFoot, leftFootObj.rotation);

Puedes asignar el peso del IK, mientras más cercano al 1 se encuentre menos fuerza tendrá la animación. 

Revisa esta sección, está perfectamente explicado y en español.
https://docs.unity3d.com/es/2018.4/Manual/InverseKinematics.html

Share this post


Link to post
Share on other sites

Buenas tardes Francoe1, llevo prácticamente todo el día tratando formas de solucionar el problema porque la versión de Unity que uso es la 4.7.2 y no tiene las funciones de las que habla o al menos no se las encuentro por ningún sitio, aunque debe de poder hacer lo mismo de otras formas, porque en un vídeo vi como explicaban que en las últimas versiones de Unity se pueden aplicar por ejemplo filtros postprocesado a la cámara y resulta que en mi versión (que pensaba que no se podía hacer) también los puedo usar, aunque de otro modo. No hay tantas diferencias entre las últimas versiones y anteriores y puede que incorpore esto de Mask Avatar mi versión también.

Se que me va a decir que actualice Unity, pero si no lo he hecho ya es porque mi proyecto comenzó a realizarse con una versión muy antigua de Unity, la 2 o por ahí, ya que no tenia un PC potente y necesitaba una versión con pocos requerimientos técnicos. Después me he comprado un PC gaming que está bastante bien y que mueve todos los juegos en Ultra, actualicé a la última versión de Unity, importé mi proyecto y adivine, me echó a perder todo el trabajo porque muchas cosas no funcionaban igual, la iluminación era diferente y un montón de cosas, así que tuve que ponerme a buscar la última versión que me mantuviese los progresos que ya había realizado en mi proyecto y era la 4.7.2.

Solo me quedan dos opciones, encontrar el Avatar Mask (o como se llame en mi función de Unity) o programar para que me haga lo mismo y de hecho esta tarde he conseguido que funcione, pero no del todo bien. La solución va por aquí:  

transform.rotation = Quaternion.Lerp (transform.rotation, Rotacion * Correccion, FUERZA_MOVIMIENTO * Time.deltaTime);

Si la fuerza que aplicamos al Quaternion.Lerp es baja, no contrarresta la fuerza de la animación del Animator, pero si la vamos subiendo va haciendo el giro progresivo. Por lo que he creado una variable para poder controlar esa fuerza cuando yo quiera subiendo el número de la variable progresivamente hasta 100 y cuando quiero que deje de mirar al objeto, bajo el número de la variable a 0 y vuelve a su sitio progresivamente. Aunque seamos honestos, esto es una chapuza y seguro que me da problemas.

A ver si podemos solucionarlo. ¿Que versión de Unity es la primera que ya incorpora el Mask Avatar? (para instalarla y ver no me jode mucho el trabajo realizado),

Saludos.

Share this post


Link to post
Share on other sites

Si no mal recuerdo Mask Avatar aparece junto Animator Controller, version 4.0. 

Fíjate que deberías tenerlo, yo use mucho tiempo la 4.2.x y tenía Avatar Mask. 

Share this post


Link to post
Share on other sites
On 2/1/2020 at 7:26 PM, francoe1 said:

Fíjate que deberías tenerlo, yo use mucho tiempo la 4.2.x y tenía Avatar Mask. 

Y va estupendo para mezclar animaciones y conseguir estados como "correr mientras disparas", o similares... :91_thumbsup:

Share this post


Link to post
Share on other sites
Sign in to follow this  

×
×
  • Create New...