Jump to content
Sign in to follow this  
jaunco325

ANSWERED duda sobre el transform.position y colisiones

Recommended Posts

tengo entendido que mover un objeto a traves de su transform puede causar que no detecte algun collider, ya sea collision o trigger. hay alguna forma de solucionar esto sin recurrir al movimiento por rigidbody?

otra pregunta: el problema antes mencionado solo ocurre con los objetos que se mueven rapido o tambien les puede pasar a los que se mueven lento?

Share this post


Link to post
Share on other sites

Hablo por experiencia propia, la cual no es demasiada, de modo que si me equivoco corregidme

 

Yo lo que hago es usar transform.translate, asta ahora no me a dado ningún problema...

Y no, no depende de la velocidad,lo que pasa es que cuando modificas la posición directamente las colisiones no se actualizan...

pero no lo tengo muy claro :7_sweat_smile:, espero que lo primero que te e explicado te sea útil 

Aquí tienes un vídeo que te puede ayudar

 

Share this post


Link to post
Share on other sites
On 3/21/2020 at 3:25 PM, jaunco325 said:

tengo entendido que mover un objeto a traves de su transform puede causar que no detecte algun collider, ya sea collision o trigger. hay alguna forma de solucionar esto sin recurrir al movimiento por rigidbody?

Por un lado tenés Transform (pos,rot y escala), que se utiliza principalmente para el renderizado, es decir antes de realizar el render del frame se leen los datos de este transform, se procesan en el shader (basicamente creando una gran matriz) representando en 2D (tu pantalla) un objeto ficticio en 3D proyectado (ortonormal o perspectiva) sobre una cámara dada. Como regla, asocia al Transform al render.

Por otra parte están las físicas, que trabajan con el concepto de collider + rigidbody. Siempre al final de cada update físico se pasan los datos del rigidbody (pos y rot) al transform. Las físicas hacen lo suyo y a lo último actualizan el transform, así vos podés ver en pantalla lo que pasa, de lo contrario estaría todo congelado. Las colisiones y demás pasarían internamente pero no serías capaz de verlas en pantalla.

 

Este es un resumen usando un caso en concreto, modifcando rigidbodies en fixedUpdate y modificando transforms en update:

image.png

 

Fijate como una vez que te metés con rigidbodies, al transform solamente se le pasan los datos del rigidbody (sincronización RB -> T ) para que este renderize. PERO, el mundo del rigidbody no está enterado si luego vos modificas el transform.

Siguiendo con el video de ejemplo de arriba, este es el porqué se ven esos tembleques en pantalla, transform dice "nos vamos para adelante" y el rigidbody dice "no, hay un muro adelante!" y como Update suele correr más veces que la simulación física, parece como que Update gana hasta que la simulación entra y lo tira para atrás.

Por esta razón usar las físicas (es decir, usar rigidbodies) y modificar los datos del transform es contradecirte a vos mismo.

 

El video de arriba está casi completamente mal dado, así que cuidado.

  1. En los dos primeros casos está moviendo un rigidbody dinámico usando Transform, lo cual está horriblemente mal. Entiendo si lo hizo para mostrar lo mal que está, pero lo preocupante es que en un momento dice "Este método es el que más uso", cosa que me incomoda.
  2. En el caso de la fuerza está aplicandola en Update ... se hace en FixedUpdate.
  3. En MovePosition dice que funciona como transform.position , cosa que está tremendamente mal. Funciona como rigidbody.position, que no es lo mismo (ver el diagrama de arriba). Normalmente no funciona así, esto pasa solo con rigidbodies dinámicos. MovePosition se suele usar para rigidbodies kinemáticos. También usa Update.
  4. En el de velocity otra vez usa Update.

 

TL;DR:

Si tenés un rigidbody en tu código, andá mirando a los transform con cuidado, no solo a la hora de escribirlos (que claro que está mal), sino también a la hora de leerlos. Si dentro de tu loop moviste al rigidbody (rigidbody.position) el transform no lo va a reflejar para nada, son dos conjuntos de datos separados uno de otro.

 

Saludos.

  • Like 1

Share this post


Link to post
Share on other sites

Genial @lightbug. Qué gran explicación como solución para un problema que muchos al empezar no conseguimos entender de una sola vez.

Share this post


Link to post
Share on other sites
11 hours ago, iRobb said:

Genial @lightbug. Qué gran explicación como solución para un problema que muchos al empezar no conseguimos entender de una sola vez.

:91_thumbsup:

Agrego que me olvidé, la razón por la que puede o no pasar de largo un obstáculo es por el otro sync que me faltó explicar, comunmente asociado al "sync previo" o el "autoSync". Previo a cada update físico se realiza un sync, esta vez de T -> RB.

Entonces se puede dar algo como esto:

  1. T -> RB (Sync)
  2. FixedUpdate: Se modifica RB
  3. Simulación
  4. Rb -> T (Sync)
  5. Update: Se modifica T --> Render
  6. Update: Se modifica T --> Render
  7. Update: Se modifica T --> Render
  8. Update: Se modifica T --> Render
  9. T -> RB (Sync) <--- Acá se lee que pasan los datos del transform al RB (notar que el RB quedó con los datos del punto 3)
  10. FixedUpdate: Se modifica RB
  11. Simulación ... acá es donde puede estar el problema (dependiendo de las propiedades del collider y de los dos pasos anteriores)
  12. Rb -> T (Sync)

 

──────────────────────────────────────────────────────────────────────────

Acá dejo un documento interno de los devs de las físicas por si alguno está interesado en la parte del autoSync (está en inglés):

Priorly, each change of a transform resulted in a synchronous update of the corresponding physics object (if present). That always happened on the main thread and could accumulate to
quite a large number over the frame. That approach was easy to maintain, but the downside of always keeping the physics world in sync with the transform hierarchy was that we ended up writing to the physics engine too often, possibly updating some physics objects a lot more frequently than might be needed.


One particular example is moving the root transform of a ragdoll with N rigidbodies in it (=N physics bones). Once you moved the root from script, there was a message sent to update all
the child transforms down in the hierarchy. Each of those child transforms accepted the message, updated itself, and sent out another message to all the children of its own. This
naturally stacked up, leading to O(N 2 ) complexity of updating a ragdoll. In order to solve that, we have introduced a mechanism of deferred physics updates. With this
new approach, we don’t write the transform changes immediately. Instead, we store them in a buffer and apply at a later stage. Updates to the same transform are combined together and
applied as a single update to the final pose (e.g. two updates to a transform become a single update right to the final pose in the buffer).


We always sync transforms prior to running the physics simulation in order to make sure we simulate the latest poses. However, you can run the sync process manually too, using the new Physics.SyncTransforms() function. This makes sure that the transforms in Unity and the ones used by the physics engine are exactly the same.
 

By default, we run in a compatibility mode that would automatically sync before running the operations that required the up-to-date transforms before [Para 2018.3 en adelante esto está desactivado por defecto]. That is:

  •  Before all the physics queries (e.g. Physics.Raycast, etc)
  • Before reading data back from the physics engine directly (e.g. Rigidbody.position)
  • Before simulating particles, if they were configured to compute collisions
  • Before updating the camera flares effect


As mentioned above, synchronising the transforms might be a costly operation so it’s recommended to avoid doing it without the need. For this reason, you can even switch off the
automatic sync, via Physics.useAutoSyncTransforns.

 

Share this post


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

×
×
  • Create New...