Jump to content
UnitySpain
Sign in to follow this  
totemalf

Tembleque al usar fisica

Recommended Posts

Buenas, estoy haciendo pruebecillas con las diferentes formas de mover objetos con scripts. Sumando la position o usando el translate el movimiento es perfecto, totalmente fluido, pero cuando uso fisicas noto un leve tembleque en los objetos, da igual si uso velocity, o moveposition... Es esto normal? He tratado de mejorarlo con la interpolacion y extrapolation, quizas con esta segunda mejora algo, pero se sigue notando un pelin... Resumiendo, mi pregunta es si es un precio a pagar por usar el motor de fisica o es que a mi me esta pasando algo raro. Por cierto, estoy usando la ultima version alpha de unity 2020. Saludos, as

Share this post


Link to post
Share on other sites

Se puede deber a.

1º La forma del collider

2º Los materiales de colisión que estén actuando.

3º La masa del objeto.

4º (Sleep mode) La configuración de actualización de físicas.

5º (Interpolate) El modo de interpolación.

Muchas variables .... 

 

Share this post


Link to post
Share on other sites
3 hours ago, totemalf said:

Resumiendo, mi pregunta es si es un precio a pagar por usar el motor de fisica o es que a mi me esta pasando algo raro

No, debería ir todo super fluido.

3 hours ago, totemalf said:

Resumiendo, mi pregunta es si es un precio a pagar por usar el motor de fisica o es que a mi me esta pasando algo raro. Por cierto, estoy usando la ultima version alpha de unity 2020.

Cómo es que estás moviendo el objeto?, necesitamos código para poder contestarte con certeza, sobretodo con estos temas que son extremadamente delicados. Siempre ojo con una alpha. Dicho esto, te tiro algunos datos sueltos que quizás te ayuden a entender un poco más este mundo.

Dos mundos:

  1. Transform: transform.position, transform.Translate, transform.Rotate , etc...
  2. Físicas: rb.position, rb.MovePosition(...), rb.velocity, rb.AddForce( .. ) , etc ...

Nunca nunca nunca mezclar estos mundos, por ej teniendo un Rb dinámico y moverlo usarlo Transflate. Existen casos y casos, en general no es recomendado.

Yo me manejo 100% con rigibody en FixedUpdate, para mi Transform se usa para leer cosas muy específicas, o para cuestiones de Gizmos y demás, para el resto lo elimino de mis scripts (por lo menos los evito si necesito un comportamiento físico).

 

Funcionamiento de las físicas (muy por arriba):

El truco está en entender cuando las físicas hacen lo suyo y qué es lo que hacen. Basicamente cuando se da un step de simulación se realizan dos cosas (muy resumido):

  1. los physics queries (raycast, spherecast, etc)
  2. se determinan las velocidades de los rigidbodies en base a choques, materiales, etc.

Una vez que esto termina se hace un "Sync", esto basicamente actualiza el componente Transform (RB -> T), que determinara visualmente donde estará el objecto. Gracias a esto es que sin tocar el Transform vos podés ver los resultados en pantalla. Que dicho sea de paso, el motor lee el componente Transform para mostrar las cosas en pantalla, todo lo visual está directamente relacionado a este (las físicas pueden recalcular todo de arriba a abajo y nada se va a actualizar en pantalla).

AutoSync:

Si tu objeto es kinematico y lo movés usando Transform es probable que para versiones viejas de Unity no hayas notado la diferencia con moverlo "legalmente" usando físicas. Probablemente todo haya resultado fluido, esto es porque antes se usaba "autoSync" por defecto. Este autoSync lo que hacía era detectar un cambio en un transform y recalcular toda la parte de las físicas, actualizando el Collider, la pos y rot del rigidbody. Osea que estaba todo perfectamente sincronizado (T -> RB). Desde ya que esto demandaba mayor procesamiento. Hoy en día este autoSync está desactivado por defecto, demandando mayor preocupación por parte del programador a la hora de mover un rigidbody, o de realizar simples queries.

Interpolación:

Un poco más complicado de entender, pero similar a lo anterior. Por qué usar interpolación? si movés un rigidbody usando FixedUpdate (como debe de ser) vas a notar que los cambios pasan a 50 fps por defecto (probablemente no tan notable,). Si esta tasa de refresco fuera cada vez menor los cambios se harían más y más notables. Como se soluciona? interpolando estos valores, ya que el Transform está más al pedo que bocina de avión, se lo usa para generar visualmente (recordar lo que dije más arriba) un resultado, mientras las físicas laburan. En el mundo transform se van a generar posiciones y/o rotaciones intermedias, es decir, va a interpolar las pos y rots para generar visualmente un resultado.Con velocity pasa lo mismo si tenés interpolación activada.

MovePosition sirve si tenés un RB Kinemático con interpolación activada. Un dato extra: Si llamás a MovePosition estando en la pos A, y le decís "movete a B" ( rb.MovePosition(posB) ), vas a notar que la rb.position no se actualiza para nada (es igual a posA). Esto es porque MovePosition se actualiza después del step físico.

FixedUpdate:

El step físico (que hace todo lo de arriba y más) ocurre después de cada FixedUpdate, entonces si vas a mover algo usando físicas (ya sea un Rb dinámico o kinemático) lo lógico es hacerlo en FixedUpdate y no en Update.

 

Espero que sirva de algo, quizás estás metiendo la pata en alguno de esos puntos, o quizás en alguno que no mencioné. De todos modos sería útil si subieras el código que utilizas.

 

Saludos

Share this post


Link to post
Share on other sites

Wow, master class. Muchas gracias, 

a ver si mañana saco tiempo para trapichear el tema, y lo pruebo de nuevo, y en la versión actual, a ver si va a ser por la alpha. En cuanto lo tenga montado pego el código por aquí a ver... esto no es como montar en bici, lo dejas diez años y luego cuesta :P

Share this post


Link to post
Share on other sites

Buenas tardes, estoy con el mismo problema y por lo que veo el tema de las físicas es muy extenso, pero para empezar comprendiéndolo lo primero que deberíamos de ver es que fuerzas se usan para cada tipo de movimiento.

Si uno mira los manuales y los tutoriales de Internet se da cuenta de que por ejemplo para hacer a un personaje saltar usan rigidbody.velocity, mientras que para hacer que avance hacia delante usan rigidbody.AddForce y como estas fuerzas a veces son opuestas si no están bien montadas causan tembleques o dan problemas.

- ¿Que fuerzas existen para aplicar al rigidbody y para que casos se usan?, aunque sea explicarlo solo por encima y no entrando en demasiado detalle, ¿para que avance un personaje solo tenemos rigidbody.AddForce?.

Un saludo.

Share this post


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

Si uno mira los manuales y los tutoriales de Internet se da cuenta de que por ejemplo para hacer a un personaje saltar usan rigidbody.velocity, mientras que para hacer que avance hacia delante usan rigidbody.AddForce y como estas fuerzas a veces son opuestas si no están bien montadas causan tembleques o dan problemas

6 hours ago, Jhonatan00_00 said:

- ¿Que fuerzas existen para aplicar al rigidbody y para que casos se usan?, aunque sea explicarlo solo por encima y no entrando en demasiado detalle, ¿para que avance un personaje solo tenemos rigidbody.AddForce?.

En general no existen reglas, podés hacer lo que quieras, todo dependerá del tipo de resultado deseado.

"Si se mueve y te gusta el resultado, está bien" - Lightbug, enero de 2020.

Por ejemplo: asignando la velocidad de manera absoluta te da algo super exacto, basicamente querés que el cuerpo vaya a tal lugar y lo tenés. Todavía tenés alguna que otra cosita que te puede modificar el comportamiento (drag, angular drag, materiales físicos, etc) pero tenés trucos para todo esto.

Si por el contrario querés que la simulación sea 100% real life no fake entonces asignar la velocidad de manera absoluta (lo remarco de nuevo) es lo peor que podés hacer.

En este mundo tenés similaridades con el cálculo diferencial. Disponés de "órdenes de control" sobre la posición y rotación:

  • orden 0: (sin derivar): Posición y rotación -> basicamente personajes kinemáticos
  • order 1: (derivando lo anterior) -> velocidad lineal y velocidad angular -> rigidbodies dinámicos
  • orden 2: (resultado de derivando lo anterior) -> Fuerza y Torque. -> rigidbodies dinámicos

Mientras mayor es el orden tenés menor control. Notá que para el orden 2 no podés anular la velocidad de golpe, vas a obtener un resultado más realista (no necesariamente un mejor resultado).

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

Por ej para el orden 2 es muy útil utilizar controladores PID para realizar movimientos algo precisos empleando fuerzas.

En resumen, tenés una entrada de referencia con velocidad = v (puede ser cualquier valor), esta señal pasa por unos bloques de compensación (el PID) luego la velocidad de salida se realimenta a la entrada y se calcula la diferencia entre este resultado y la velocidad de set v. Esto finalmente reingresa al loop y así forever. La velocidad de salida tenderá al valor de set, esto por las características del PID, también dependerá mucho de la elección de los parámetros Kp Ki y Kd.

Aca un vid con un ejemplo de posición:

Todo esto es teoría de control, el tema es bastante complejo como para entenderlo en un post. Hay mucho material muy interesante.

Share this post


Link to post
Share on other sites

Buenas tardes, por lo que estoy viendo y probando, que de tirones depende también mucho del modo de actualización de la instrucción. Por ejemplo para mover un personaje estoy usando rigidbody.moveposition (transform.position + transform.forward * Velocidad * Time.deltatime); y cuando choco contra una pared empieza a temblar como si las coordenadas fallaran, se intentase meter en la pared y después lo repelera, porque creo que no está actualizando las coordenadas a la debida velocidad.

Al principio temblaba o daba tirones simplemente al moverse, no hacia falta ni que chocase con nada, pero activando la opción del Rigidbody de interpolación se soluciona. Por cierto, he observado que si tienes dos fuerzas distintas programadas (una para avanzar y otra si pulsas la tecla de saltar para que suba) y activas Interpolate una fuerza anula a la otra y no lo hace bien, en cuyo caso tienes que usar extrapolate.

La duda es, ¿de que forma actualizamos correctamente las físicas?, ¿seria mejor con Time.fixedDeltaTime, con Time.frameCount?, ¿como lo haceis?.

Saludos.

Share this post


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

¿de que forma actualizamos correctamente las físicas?,

Está en el post de más arriba. FixedUpdate, por las razones que mencioné antes.

5 hours ago, Jhonatan00_00 said:

¿seria mejor con Time.fixedDeltaTime, con Time.frameCount?, ¿como lo haceis?.

Velocidad = Δ desplazamiento / Δ tiempo

Δ desplazamiento es la cantidad de desplazamiento que le tenés que agregar a tu objeto, es decir sería tu " + transform.forward * Velocidad * Time.deltatime ": Despejando:

Δ desplazamiento = Velocidad *  Δ tiempo

De ahí sale la forma esta (que se llama de "Euler"). Todo en realidad parte desde las derivadas, pero acá te manejas con pequeños incrementos, osea el tiempo de frame a frame (no el frame count). En el mundo Unity sería:

Δ desplazamiento = Velocidad *  dt

Y cual es el dt que debés usar? bueno, eso depende (y no tanto, ahora vas a ver) del método que uses:

  • Si es Update Time.deltaTime te da el tiempo que tardó el último frame.
  • Si es FixedUpdate (<--- es este) Time.fixedDeltaTime te da el tiempo que pasó en FIxedUpdates (generalmente coincide con "Project Settings/Time/Fixed step" (creo))

Pero, y si estás en FixedUpdate y llamás a Time.deltaTIme ¿que pasa?, nada, te devuelve lo mismo que Time.fixedDeltaTime ... yo siempre uso Time.deltaTime para todo y listo.

frameCount devuelte la cantidad de frames que pasaron, osea que no es un dt, no sirve.

5 hours ago, Jhonatan00_00 said:

Por cierto, he observado que si tienes dos fuerzas distintas programadas (una para avanzar y otra si pulsas la tecla de saltar para que suba) y activas Interpolate una fuerza anula a la otra y no lo hace bien, en cuyo caso tienes que usar extrapolate.

Eso habría que ver el código, osea con "tener dos fuerzas programadas" no se entiende demasiado. Lo que sí se sabe es que se debe hacer una sola llamada a MovePosition por frame físico. --> https://docs.unity3d.com/ScriptReference/Rigidbody2D.MovePosition.html

It is important to understand that the actual position change will only occur during the next physics update therefore calling this method repeatedly without waiting for the next physics update will result in the last call being used. For this reason, it is recommended that it is called during the FixedUpdate callback.

Note:
MovePosition is intended for use with kinematic rigidbodies.

 

Share this post


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

×
×
  • Create New...