#30 WaitForFrames no lo veo en la documentacion de Unity ._.
aparece:
WaitForEndOfFrame
WaitForFixedUpdate
WaitForSeconds
WaitForSecondsRealTime
#30 WaitForFrames no lo veo en la documentacion de Unity ._.
aparece:
WaitForEndOfFrame
WaitForFixedUpdate
WaitForSeconds
WaitForSecondsRealTime
#21 No controlo de Unity pero me extraña esto que habéis comentado... FixedUpdate corre a 50 frames/segundo... pero qué pasa si el PC recibe un lag-spike y baja a 10fps aunque solo sea un momento? Creo que deberías recurrir a la variable de sistema "delta", cuyo valor es el tiempo en milisegundos desde el último frame, y usar ese valor para multiplicar cualquier velocidad. Así si tienes lag-spike, ese movimiento será más grande y por tanto más consistente.
#30 El problema que le veo a eso es que no sé cómo se contarán esos 50 frames, es decir, no sé si tendría el mismo problema que tenía al contar los coyote frames en el Update, teniendo en cuenta que esa corrutina la llamaría en el evento ontriggerexit (que es donde cambio la variable isGrounded)
Luego lo que dice Nekro, no encuentro esa función :S
#32 Sí lo había pensado, en un escenario como el que cuentas (fps por debajo de 50) podría ser inconsistente y creo que usar Time.deltaTime sería lo suyo, le tendré que dar otra vuelta al tema.
#33 Espera, estoy leyendo... si no lo he entendido mal. FixedUpdate es llamado en función de los fps actuales. Así que creo que no debes hacer nada más.
Por ponerte un ejemplo: Si el juego te va a 100fps, FixedUpdate se llama cada 2 segundos. Si el juego te baja a 25fps, se llama 2 veces por segundo. Y así todo el rato. Pero que te lo confirme alguien que entienda de Unity mejor, por ejemplo @debug (a saber qué nick está usando hoy)
#32 https://docs.unity3d.com/ScriptReference/MonoBehaviour.FixedUpdate.html
The FixedUpdate frequency is more or less than Update. If the application runs at 25 frames per second (fps), Unity calls it approximately twice per frame
Si te da un lag a 10 fps, el motor llamará fixedupdate 5 veces por frame.
#35 Vale, lo acabo de leer. Pues mete ahí cualquier movimiento y pista. Lo que no entiendo por qué te dan el DeltaTime si no lo tienes que usar nunca ¿?
#34 De hecho lo probe forzando los fps (o como dice tote semi-forzando) a 20 y parecía funcionar bien, esto del Update/FixedUpdate me trae de cabeza...
Había pensado en quotear a d-bug también, pero ya le perdí la pista del nick actual xDD
#35 Entonces salvo que alguien nos corrija, de momento podemos decir que lo tengo de forma correcta. ¡Y sin demasiado código!
Esto he encontrado, una clase para implementar ese waitfor.frames: https://ivanderevianko.com/2015/05/unity3d-waitforframes-in-coroutine
Que entiendo que llamando a la corrutina en FixedUpdate debería funcionar, pero en mi caso no lo sé (por puro desconocimiento) ya que mi variable isGrounded se actualiza en el evento ontriggerexit. A lo mejor dicho evento, al ser parte de las físicas (creo), se ejecuta en fixedupdate, pero lo ignoro por completo.
#41 Con lo sencillo que lo tengo ahora... Así ha quedado después de todo lo hablado:
private bool isGrounded;
private int actualCoyoteFrames ;
private int maxCoyoteFrames = 5;
private bool CheckCoyoteTime() {
return actualCoyoteFrames < maxCoyoteFrames;
}
private void SetCoyoteTime() { // Se llama en el FixedUpdate
if (!isGrounded){
actualCoyoteFrames++;
else
actualCoyoteFrames = 0;
}
// En la función de salto
if (InputController.Jump && !alreadyJumped && (isGrounded || CheckCoyoteTime())){
// Haz que salte
}
Estas haciendo doble check a lo mismo.
Porque solo subes el contador del coyotetime si !isGrounded, pero aun asi en la funcion de salto pones isGrounded || CoyoteTime pero es que si isGrounded es true, el CheckCoyoteTime() siempre te va a devolver true.
Asi que puedes dejar como:
if (InputController.Jump && !alreadyJumped && CheckCoyoteTime()){
// Haz que salte
}
Igual mi explicacion es liosa:
Si isGrounded es verdadero -> actualCoyoteFrames = 0
Si actualCoyoteFrames es 0 -> CheckCoyoteTime() = verdadero
(isGrounded || CheckCoyoteTime())
Siempre te devuelve el valor que tenga CheckCoyoteTime();
#43 Toda la razón del mundo, la función de salto es anterior a lo del coyote time y ni lo había pensado.
Pues así queda la versión final:
private bool isGrounded;
private int actualCoyoteFrames ;
private int maxCoyoteFrames = 5;
private bool CheckCoyoteTime() {
return actualCoyoteFrames < maxCoyoteFrames;
}
private void SetCoyoteTime() { // Se llama en el FixedUpdate
if (!isGrounded){
actualCoyoteFrames++;
else
actualCoyoteFrames = 0;
}
// En la función de salto
if (InputController.Jump && !alreadyJumped && CheckCoyoteTime()){
// Haz que salte
}
Y van tres
Hostias, que no actualiza el input durante fixedUpdate, vaya vaya xDDDD
Eso si que me ha dejado roto xDDDD
#45axn:Captura el tiempo al salir del collider y después en el salto determinas con ese timestamp si ha finalizado el Coyote Time.
Esto me gusta, y no tienes que modificar mucho el codigo para hacer esto @obZen
#45 Vale, voy a necesitar un tiempo para digerir todo eso, de momento voy a ir viendo lo de hacerlo contando el tiempo. Muchísimas gracias por tan detallada respuesta!
#46 Lo del input en el FixedUpdate sí que lo sabía y me había generado ya algún dolor de cabeza, lo explico en uno de los posts del principio, de por qué estaba usando una clase que había encontrado en github para facilitar ese tema.
#48 Hmmm lo he hecho así:
private float actualCoyoteTime;
private float maxCoyoteTime = 0.2f;
private bool CheckCoyoteTime()
{
return actualCoyoteTime < maxCoyoteTime;
}
private void SetCoyoteTime() // Se llama en el FixedUpdate
{
// isGrounded se calcula en los eventos de entrada y salida de colisionadores de tierra
if (!isGrounded)
{
actualCoyoteTime += Time.fixedDeltaTime;
}
}
// En la función de saltar
if (inputController.Jump && !alreadyJumped && (isGrounded || CheckCoyoteTime())) { // Salto }
Aunque entiendo por lo que ha dicho #45 que da igual que use Time.fixedDeltaTime o Time.deltaTime porque si uso el segundo desde FixedUpdate me devolvera el primero de todas formas.
tienes que resetear actualCoyoteTime a 0 cuando isGrounded te devuelve verdadero en SetCoyoteTime().
Esa opcion la contemplé pero en mi mente era mas costosa computacionalmente.
Si vas a usar DeltaTime no hace falta que pongas fixedDeltaTime y en verdad lo puedes meter en el mismo Update si quieres, en caso de que tengas problemas de rendimiento va a tener menos impacto, y en caso de que tengas mas de 50 fps, va a ser mas fiable.
#50 Ah sí, que no lo puse, reseteo a 0 el actualCoyoteTime en cuando pongo a true isGrounded en el evento de entrada al colisionador.
Lo del deltaTime o fixedDeltaTime entiendo que puedo poner siempre deltaTime y Unity me devolverá uno u otro dependiendo de si se está llamando desde Update o desde FixedUpdate, o eso he entendido!
Lo de ponerlo en Update no me convence, teniendo en cuenta que se recomienda poner los cálculos que tengan que ver con físicas en FixedUpdate. Voy a acabar soñando esta noche con Unity ya verás... que me he pasado la tarde pegándome con el sistema de escaleras que tenía, que quería mejorarlo y ahora de vueltas con el Coyote Time xDD
#52 Vale, entonces se me simplifica incluso más, ya que no tengo que sumar incrementos de delta ni nada:
Guardo Time.time al salir del colisionador y luego compruebo que Time.time - timeGuardado < maxCoyoteTime y listo.
private float maxCoyoteTime = 0.2f;
private float actualCoyoteTime;
private bool CheckCoyoteTime()
{
return Time.time - actualCoyoteTime < maxCoyoteTime;
}
actualCoyoteTime = Time.time; // En la salida de la colisión del suelo
if (inputController.Jump && !alreadyJumped && (isGrounded || CheckCoyoteTime())) { // Saltamos }
#54 Sí, eso lo leí en la documentación por eso a priori no me convencía la solución de n3krO, pero porque todavía iba con la idea de usarlo frame a frame, que no es el caso. Muchas gracias por la ayuda!
#54 Yo eso lo pensé, pero no me gusta la solución que yo le daria xDDDDD
Yo lo que entiendo es que recomiendas esto:
if (inputController.Jump && !alreadyJumped) {
if (isGrounded || CheckCoyoteTime()) { // Saltamos }
}
#56 Le daré unas vueltas a eso, no creo que me cueste mucho implementarlo ya que ya tengo una clase separada que se encarga de gestionar/almacenar el input. Entiendo que lo único que debería hacer es que tuviera su propio Update y luego jugar con el orden de ejecución.
#57 Yep! Así me evito llamadas innecesarias a CheckCoyoteTime y por ende a Time.time. Lo cambio ahora mismo.
#59 Ya he hecho el cambio, en el orden de ejecución de scripts lo he puesto el primero:
Supongo que no tengo que hacer nada más, todos los de abajo de PlayerInput o los que no salen en la lista se ejecutarán después.