Jump to content
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 .... 

 

  • Like 1

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

  • Like 1

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.

  • Like 1

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.

 

  • Like 1

Share this post


Link to post
Share on other sites

Buenas tardes, he solucionado los problemas de los tembleques simplemente cambiando el método de actualización del proceso principal del script. No entendía a Lightbug porque no había dicho que la forma de actualización de un script no puede darse solo en un comando para por ejemplo desplazar un objeto con transform, si no en todo un proceso completo.

Me  explico: Cuando creamos un script tenemos dos procesos ya creados, uno es void Start (para inicializar cualquier parámetro) y otro es void Update (el proceso que actualiza los frames). En este proceso que actualiza los frames tenemos que cambiar el Update por FixedUpdate para que actualice las físicas correctamente y listo.

A mi me van bien ahora y no tiene mas complicación, aunque es un error por parte de Unity, ya que nosotros queremos un engine para crear videojuegos y listo, no para estar solucionando problemas que ya debería de solucionar por si solo, ¿por que crean el FixeUpdate cuando funciona igual que un Update pero sin errores en las físicas?, para eso usas siempre FixeUpdate y listo... no lo entiendo.

Un saludo.

Edited by Jhonatan00_00

Share this post


Link to post
Share on other sites
44 minutes ago, Jhonatan00_00 said:

Buenas tardes, he solucionado los problemas de los tembleques simplemente cambiando el método de actualización del proceso principal del script. No entendía a Lightbug porque no había dicho que la forma de actualización de un script no puede darse solo en un comando para por ejemplo desplazar un objeto con transform, si no en todo un proceso completo.

Me  explico: Cuando creamos un script tenemos dos procesos ya creados, uno es void Start (para inicializar cualquier parámetro) y otro es void Update (el proceso que actualiza los frames). En este proceso que actualiza los frames tenemos que cambiar el Update por FixedUpdate para que actualice las físicas correctamente y listo.

A mi me van bien ahora y no tiene mas complicación, aunque es un error por parte de Unity, ya que nosotros queremos un engine para crear videojuegos y listo, no para estar solucionando problemas que ya debería de solucionar por si solo, ¿por que crean el FixeUpdate cuando funciona igual que un Update pero sin errores en las físicas?, para eso usas siempre FixeUpdate y listo... no lo entiendo.

Un saludo.

Te voy a contestar nuevamente intentando no herir tus sentimientos.

2 cosas importantes antes de empezar, la definición de comando está muy alejada de lo que realmente quieres expresar, en dicho caso deberias utilizar algo referente al código, por ejemplo, línea de código,  API, etc. Segundo, lo que estás llamando proceso se define como Función, son cosas demasiado diferentes para confundirlas. 

Ahora dejando claro lo anterior vamos al tema del ¿por qué se utiliza más de una función de actualización?, el por que es simple, Unity como todos los motores gráficos que existen tienen un variable que se conoce como GameTime esta variable Unity la llama deltaTime, no es más que el tiempo que pasó desde el último frame al actual, esto nos sirve para crear una lógica consistente. EJ. si intentas trasladar un objeto sin deltaTime este dependerá de cuantos FPS tengas en el momento, sin embargo si multiplicas esto por deltaTime entonces compensaras el movimiento entre diferentes FPS, esto es una simple regla de 3 simples.

¿Por que FixedUpdate?
La separación de Update y FixedUpdate se debe a una decisión de diseño y una solución a Physics Pass, mientras la función Update se llama en cada frame, la función FixedUpdate se puede llamar 1, 0, o varias veces todo depende del Physics Pass y la configuración del proyecto. Las físicas no solo hacen que tu Rigidbody se mueva, si no, tiene que calcular los Hitbox, contacts, triggers, joins y todos lo componentes físicos que existan en la escena.

¿Por qué no usar siempre FixedUpdate?
Por la misma razón que no colocas la lógica del Juego dentro de la función Start o Awake, por que no se trata de la función que deriva del Game Loop.

 

Si estás interesado en saber más te recomiendo LEER lo siguiente donde explica muy bien el ciclo de vida de un juego.
https://ir.lib.uwo.ca/cgi/viewcontent.cgi?referer=&httpsredir=1&article=1138&context=electricalpub

Suerte!

  • Like 1

Share this post


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

No entendía a Lightbug porque no había dicho que la forma de actualización de un script no puede darse solo en un comando para por ejemplo desplazar un objeto con transform, si no en todo un proceso completo.

4 hours ago, Jhonatan00_00 said:

...aunque es un error por parte de Unity, ya que nosotros queremos un engine para crear videojuegos y listo, no para estar solucionando problemas que ya debería de solucionar por si solo...

No, una cosa es un error, un fallo, algo que está puesto así que no debe ser así. Unity tiene muchos mensajes, callbacks o como los quieras llamar. Justamente, es porque queremos un engine para crear juegos que ellos ponen a disposición todos estos callbacks. Desde ya que en Unity Technologies no tienen una bola mágica para adivinar qué es lo que los millones de usuarios van a hacer, en plan de "ciclo de update para todos y todas". Quizás OnAnimatorIK resulte útil para actualizar el transform de los IK. Si tuvieras que procesar algo cada vez que un contacto ocurra será OnCollisionEnter, para otra tarea como reconocer inputs vendrá bárbaro Update, para aplicar fuerzas a un rb será FixedUpdate, y así. Como te dice Franco, dependiendo del "game loop" te resultará Start, Update, FixedUpdate, etc. Ellos simplemente destripan todo el loop y te lo dan en forma de callbacks o mensajes.

Acá tenés una lista completa (bajá hasta "Messages"):  --->   MonoBehaviour

4 hours ago, Jhonatan00_00 said:

¿por que crean el FixeUpdate cuando funciona igual que un Update pero sin errores en las físicas?, para eso usas siempre FixeUpdate y listo... no lo entiendo.

Todo esto está más que detallado en la documentación:

Execution Order

FixedUpdate

FixedUpdate should be used instead of Update when dealing with Rigidbody. For example when adding a force to a rigidbody, you have to apply the force every fixed frame inside FixedUpdate instead of every frame inside Update.

Bueno, creo que Franco ya lo explicó arriba. Es por el tema de la simulación física. Este concepto no es algo fácil de agarrar si recién empezas con motores en general, y eso que estamos hablando de Unity que es relativamente amigable.

Para obtener resultados coherentes los motores físicos usan un "Tick" fijo, usando un fixed delta time. Con lo que mencioné arriba de autoSync, desde 2017 (creo) hacia adelante empezó el proceso de abandonar la sincronización automática entre Transform y cuerpo físico. Esto significa que si vas a tocar (en cualquier forma) a un rigidbody o collider asociado debés usar FixedUpdate , ya que estos forman parte de las físicas de motor (si es que querés hacer las cosas bien, claro que podrías reactivar autosync y fué, pero esto no es una buena práctica). Es decir, el único momento en el que el cambio tiene notoriedad es luego de que haya pasado el  "update físico" (Internal physics update). Vos debés modificar los valores justo antes de este update físico. Y donde está dicho Update? bueno para tener 100% conociemiento de esto te pasé lo siguiente ---> Execution Order

e.jpg

Fijate que OnAnimatorMove es válido, pero solo se da cuando el animator se mueve (??, ir a la doc), OnStateMachineenter/Exit es válido, y pero si no tuvieras una state machine de Animator? como vez todos estos podrían llegar a funcionar pero dependen de componentes de animación y de eventos en concreto (enter/exit,OnMove, etc). Entonces, ¿Cual de estos bloques te asegura que se ejecute una y otra vez sin depender de ningun componente? --> Fixed Update

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Estos temas no son super fáciles de agarrar a la primera. Te recomendaría crearte un proyecto separado (o escena separada) y empezar a jugar con esto. Imprimiendo en consola mensajes, dibujando rays, lo que sea que te ayude más a entender toda esta estructura (ya que es lo básico). Pero ojo, esto no significa que cualquiera que haga juegos por ahí se sepa esto al 100%, me atrevería a decir que probablemente el 40% de los que usan y crean juegos en Unity (hasta juegos comerciales) ni siquieran se saben que FixedUpdate está sobre el mismo hilo que Update. En el foro oficial ves a usuarios "pro" que dicen que Update y FixedUpdate corren de manera separada en sus mundos, como si fueran dos hilos completamente distintos (a pesar de que el diagrama de arriba está bastante bastante claro de que esto no es así). Por eso, tomate tu tiempo, esto no se aprende en 1 día.

  • Like 1

Share this post


Link to post
Share on other sites

Buenas noches, ya veo la cantidad de información que voy a tener que procesar... creo que ya me está doliendo la cabeza solo de mirar cosas y mas cosas por encima. Cuando no entiendes algo y te esfuerzas por entenderlo te agotas enseguida y mas a estas horas.

3 hours ago, lightbug said:

Pero ojo, esto no significa que cualquiera que haga juegos por ahí se sepa esto al 100%, me atrevería a decir que probablemente el 40% de los que usan y crean juegos en Unity (hasta juegos comerciales) ni siquieran se saben que FixedUpdate está sobre el mismo hilo que Update. En el foro oficial ves a usuarios "pro" que dicen que Update y FixedUpdate corren de manera separada en sus mundos, como si fueran dos hilos completamente distintos (a pesar de que el diagrama de arriba está bastante bastante claro de que esto no es así). Por eso, tomate tu tiempo, esto no se aprende en 1 día.

Por eso mismo, no pretendan que un novato como yo o como otra persona que entra al foro con un problema super básico entienda todo eso. Es increible todo lo que saben ustedes y dudo que nunca llegue a saber la mitad, pero intento aprender sobre procedimientos prácticos, aprendiendo solo lo que me pueda servir y no teniendo que estudiar tanto para al final probablemente no usar mas que la mitad de lo que aprenda, porque en todas las carreras hay mucho de paja y poco de grano como se suele decir y no creo ni que sea necesario.

Cuando entro al foro me doy cuenta que es el mejor foro de Internet sobre Unity y es gracias a ustedes, por todo lo que saben, pero también me doy cuenta de que cuando alguien pregunta cualquier cosa suelen liarlo mucho, porque empiezan a explicar toda la teoria de un montón de cosas y a nosotros ya nos cuesta dar con la tecla para hacer una chorrada.

De todas formas no viene mal aprender, voy echándole un ojo a esto y a lo otro.

Un saludo.

 

  • Like 1

Share this post


Link to post
Share on other sites

Me gusto tu respuesta! con esa actitud deberías responder siempre.

1 hour ago, Jhonatan00_00 said:

pero también me doy cuenta de que cuando alguien pregunta cualquier cosa suelen liarlo mucho.

Esto no es algo intencional, imaginate que vos no entendes ciertas cosas por lo cual tu contexto está basado en tus conocimientos, para darte una respuesta real debería conocerte y poder contextualizar las cosas. Es por esta razón que siempre intento contestar de la forma que creo más correcta, de esta manera puedes seguir buscando información relacionada y solucionar tus problemas.

Algo muy importante, si quieres aprender lo mejor es leer toda la documentación de Unity es corta y tiene información muy importante para entender muchos conceptos, yo la he leído varias veces, algunas en inglés y otras en español, mi ingles no es muy bueno y me costo baste pero mis ganas de entender superan esas limitaciones. 

Anímate a Leer, los videotutoriales son un arma de doble filo, si bien lograr un resultado más inmediato es muy dificil asimilar los concepto, sobre todo, por que mucha gente que hace tutoriales no sabe el porqué ni el concepto de las cosas.

 

Saludos.

  • Like 1

Share this post


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

×
×
  • Create New...