Jump to content
nomoregames

Simulación de children transform

Recommended Posts

Hola a todos

Uno de los principales motivos por el que convierto un objeto a hijo de otro, es, por el modo en el que se liga el transform de el padre, a el transform de el hijo, haciendo que si giras el padre, su "retoño" gire de igual manera.... el caso es que quiero hacer el mismo tipo de transform pero por script, sin tener la necesidad de hacer ni padres ni hijos...

Alguna idea, esto me tiene desesperado

Gracias de antemano 

Share this post


Link to post
Share on other sites

Te recomiendo seguir utilizando los objetos anidados, para eso se creó el componente Transform,  de lo contrario deberias recrear un componente similar lo cual no vale la pena.

Share this post


Link to post
Share on other sites

Disculpa mi ignorancia :7_sweat_smile:, pero creo que no te he entendido bien...

Quieres decir que no hay un modo sencillo de hacerlo?

 

Share this post


Link to post
Share on other sites

Quieres copiar la forma de movimiento entre dos objetos en la jerarquía si tener que hacerlos padre/hijo?

Quote

 

Public Transform Parent;

gameObject.transform.position = Parent.position;

 

Y has lo mismo con la rotación. En sus ejes XYZ

Edited by pioj
vigila el meter código en medio del post, puede romper el foro

Share this post


Link to post
Share on other sites

Jejejejeje

Eso mismo pensé yo... y funciona bien siempre y cuando la posición de el objeto sea la misma que la de su "no padre", probé algo similar usando, transform.forward y el resultado se acercaba algo a lo que busco... pero no 

Share this post


Link to post
Share on other sites
Quote

 


public Transform Parent;

public Vector3 Diferencia;

gameObject.transform.position = Parent.position + Diferencia;

 

 

Edited by Pathus22
por favor, usa el <> o el comment para pegar código.

Share this post


Link to post
Share on other sites

@Pathus22 y @Alex no, eso servirá para la posición pero no para toda la transformación (rotación, escalado y posición), y no de forma anidada.

@Pathus22 y @Alex: hay una forma de incluir código en los posts y que se vea bonito, os animo a usarla ;-).

@nomoregames, como bien te dice @francoe1 tienes poco que ganar haciendo tú mismo algo para lo que Unity está optimizado, y sería bueno que comentases para qué quieres hacer eso: suelen recomendar que uno pregunte por su problema, no por la que cree que es su solución!

Dicho esto...

Tu problema es un problema clásico de robótica (calcular la posición del extremo de una serie de brazos articulados), también aplicable a astronomía (satélites que rotan alrededor de planetas que rotan) y a programación gráfica (que es el caso que nos ocupa).

La manera que tenemos de atacar este problema es tirando de álgebra lineal. ¡No dejes de leer aún! Al principio es un lío, pero estos objetos matemáticos (vectores, matrices y quaterniones) podría decirse que están hechos a medida para este tipo de problemas, y explorarlo nos acerca un poco al funcionamiento de los motores y las tarjetas gráficas.

Iba a dejarte una explicación general pero no me veo capaz. Si expones tu problema, intentamos ayudarte.

Te pongo una respuesta random pero realmente sería bueno saber qué quieres hacer:

  1. La posición, orientación y escalado de un objeto se pueden representar mediante un Vector3, Quaternion y Vector3 respectivamente.
     
  2. Estas operaciones (traslación, rotación, dejando el escalado aparte) son operaciones lineales,  lo que significa que las cosas que están en línea recta seguirán en línea recta después de cualquiera de estas transformaciones.
     
  3. Sabemos por el álgebra lineal que las transformaciones lineales representan una forma de "transformar el espacio" (o los puntos en el espacio). Y también que cualquier número de esas transformaciones lineales se pueden combinar en una única transformación "unificada".
     
  4. Las transformaciones vectoriales se pueden representar con una matriz.
     
    1. Cuando la matriz representa traslación, rotación y escalado, la llamamos "matriz de transformación homogénea" (y es de 4x4).
    2. En Unity se usa la clase Matrix4x4 para albergar esas matrices.
       
  5. El álgebra nos dice que para transformar un punto (un Vector3) de un espacio a otro, podemos multiplicar un vector por esa matriz. Las matrices y vectores y sus operaciones se han definido para esto: son "objetos matemáticos" hechos para facilitar la representación y las operaciones con espacios vectoriales.
     
    Vector3 traslacion = new Vector3(0, 0, 0);
    Vector3 rotacion = Quaternion.Euler(0, -30, 0);
    Vector3 escalado = Vector3.one;
    Matrix4x4 transformacion = Matrix4x4.TRS(traslacion, rotacion, escalado);
    
    Vector3 puntoOriginal  = new Vector3(4,5,6);
    Vector3 puntoTransformado = transformacion.MultiplyPoint3x4(puntoOriginal);

     
  6. Esto es bastante mágico: las matrices también se pueden multiplicar. Y esto representa geométricamente lo que uno hubiera pensado: ¡la combinación de dos transformaciones sucesivas! ¡qué bien pensadas están! (mucha gente muy lista ha tenido que morir para llegar a donde estamos :D). 
     
  7. También sabemos que todas estas operaciones NO son conmutativas (en algún caso podrían serlo, pero no en general). Así que no es lo mismo "rotar, multiplicar y escalar" que hacerlo en otro orden. Tampoco es equivalente aplicar las rotaciones en orden XYZ o en orden ZYX (los Quaterniones no tienen este problema, pero los ángulos eulerianos sí). Y tampoco por tanto podemos cambiar de orden la multiplicación de matrices al concatenarlas (esto sería equivalente a anidar padre e hijo al revés).

Por tanto, las matrices de transformación de cada nodo se multiplican sucesivamente, y el resultado se usa para transformar los vértices del modelo. Esto pone el modelo en "World Space" (ya que los vértices del modelo en sí mismo suelen estar centrados en 0, 0, 0).

Además, parecidas matrices de transformación se usan después para proyectar todos los puntos primero en el espacio de la cámara (que pulula por la escena), y luego todo en el espacio de la pantalla (2D). Esto es lo que hace la gráfica todo el rato. A la gráfica Unity le pasa realmente la última matriz de transformación, que hace toda la conversión en una única multiplicación de "vector * matriz" para cada vértice en pantalla (simplificando un poco bastante). Los vértices normalmente están ya en la memoria de la gráfica, en coordenadas locales (y no se tocan). 

Si quieres repetir este proceso, busca las matrices que te interesen, multiplícalas en el orden correcto, y finalmente multiplica tus puntos por esa matriz.

Notas:

  1. La documentación de MultiplyPoint3x4 tiene ejemplos de la transformación de un Mesh. Y también explica por qué usar ese método y no otras alternativas.
  2. Tal y como has hecho la pregunta, no puedes usar transform.worldToLocalMatrix porque tendrá acumuladas las transformaciones de sus objetos padre. De hecho Unity (cualquier motor) optimizan mucho el cálculo de estas matrices. Pero en función de tu caso, igual sí puedes aprovechar la matriz ya acumulada de un Transform.

 

Edited by J Montes
  • Like 1

Share this post


Link to post
Share on other sites

Una muy buena explicación algebraica de cómo funcionan las transformaciones. Y totalmente de acuerdo que muy posiblemente la resolución de su problema esté tomando derroteros intrincados al no conocer bien Unity.

Share this post


Link to post
Share on other sites

También sería bueno recordar que los motores gráficos ya suelen mantener la transformación local y la global por nosotros. 

En Unity, tenemos Transform.localPosition y Transform.localRotation, así como Transform.position y Transform.rotation.

Las primeras son las coordenadas locales, las que vemos en el panel de coordenadas del editor, y normalmente son las que queremos manipular. Las segundas son las coordenadas globales (las que se "dibujan"), que Unity calcula para nosotros aplicando las transformaciones acumuladas de todos los padres.

El objeto Transform de cada GameObject también nos proporciona métodos para convertir entre ambas (Transform.localToWorldMatrix y Transform.worldToLocalMatrix), que son bastante utilizados cuando toca convertir de uno a otro espacio.

También nos proporciona las propiedades .forward, .up, y .right que son vectores en world space que apuntan en esas direcciones respecto al GameObject (calcular esos vectores es muy común, y Unity nos lo ahorra).

También tenemos más directamente que usando las matrices, métodos para transformar puntos desde el espacio de un Transform al World Space (TransformDirection, TransformPoint y TransformVector).

Recomiendo revisar la documentación de Transform .

 

Edited by J Montes

Share this post


Link to post
Share on other sites

Antes de nada, darte las gracias J Montes por la info, no sabia que pudiera alcanzar tal grado de complejidad... (para mi es complejo :60_sweat:)

Explico las dos situaciones en las que quise aplicar esta solución...

Estuve tratando de hacer un modo de agarrar objetos a lo skyrim, y en parte lo logré, el problema es que el objeto que agarraba no mantenía la posición que tenia antes de cogerlo

Tengo otra situación pero ahora no me acuerdo

 

Share this post


Link to post
Share on other sites

Nunca he animado personajes 3D así que no sé cómo se hace si el personaje está animado.

Pero si la mano del personaje es un GameObject, podrías simplemente poner el objeto como hijo de ese GameObject cuando el personaje lo agarra.

Edited by J Montes

Share this post


Link to post
Share on other sites

Eso pensé, pero para darle un poco di "vida" a el asunto, hice que cuando agarras el objeto, este, mediante lerp (o slerp, no lo recuerdo bien) se dirige progresivamente hacia el final de un rayo que lanzo en linea recta desde la cámara (el rayo que utilizo también para seleccionar los objetos), el problema es que si lo convierto en hijo, no puedo hacer el lerp.... no se si me explico

Share this post


Link to post
Share on other sites

×
×
  • Create New...