Para ahorrar ancho de banda en mi juego multijugador , no actualizo cada objeto en cada tic del servidor, en cambio, cada objeto tiene una tasa de actualización que le dice al juego que se espera que este objeto se actualice cada tic del servidor X.
Cuando recibo un mensaje de actualización para un objeto, calculo el tiempo que espero que llegue la próxima actualización:
origin = serverCurrentPosition
diff = serverNextPosition - origin
arriveTime = now + timeBetweenTicks * updateRate
Cuando dibujo el objeto, calculo el tiempo que queda hasta la próxima actualización e interpolo la posición en consecuencia:
step = 100 / timeBetweenTicks * updateRate
delta = 1 - step * ((arriveTime - now) / 100)
position = origin + diff * delta
Funciona ... pero todavía hay un poco de nerviosismo en el dibujo, aunque en mi teoría todo debería funcionar bien, ya que la escala debería solucionar una cierta cantidad de retraso, ¿no?
Entonces la pregunta aquí es, ¿es este el mejor enfoque? ¿Debo poner un retraso real en el cálculo? Si es así, ¿cómo haría eso? Hice algunos experimentos, pero la inquietud solo empeoró.
fuente
Respuestas:
Tienes nerviosismo, porque el retraso está cambiando constantemente. Esto significa que, si bien el servidor envía actualizaciones exactamente cada
timeBetweenTicks
tic, el cliente las recibe después de un tiempo variable. Es probable que ese tiempo esté cerca detimeBetweenTicks
una buena conexión, pero no exactamente igual (y además, puede tener un retraso del servidor y diferentes velocidades de reloj en el servidor y el cliente).Entonces, cuando confía en recibir la actualización exactamente en el tiempo especificado, constantemente llega al destino un poco antes / después de la actualización real. Por lo tanto, nerviosismo.
Un enfoque simple para reducir la inquietud es usar "bandas de goma", que es lo que Martin sugiere en otra respuesta. Básicamente, cuando recibe una actualización, no cambia inmediatamente la posición del objeto. En cambio, si la posición del cliente y la posición del servidor difieren solo ligeramente, comienza a interpolar la posición del cliente, de modo que después de un tiempo específico (digamos, a mitad de la próxima actualización) las posiciones del cliente y el servidor convergen.
Otra idea para reducir el jitter en su configuración: dado que transmite las coordenadas "actual" y "siguiente", puede calcular la velocidad del objeto. Luego, cuando la actualización se retrasa, no detiene el objeto en su destino (es decir, la posición "siguiente"), sino que continúa moviéndolo con la misma velocidad. Si sus objetos no cambian sus velocidades abruptamente, esto realmente mejorará la suavidad del movimiento en el cliente.
fuente
He resuelto este problema anteriormente con cierto éxito con un enfoque que llamo "sombras de red". No sé si esto es algo que otras personas hacen, pero siempre me ha funcionado.
Cada entidad que se está sincronizando a través de la red tiene una entidad invisible de red invisible. Cuando llega una actualización desde la red, teletransporta la sombra directamente a la posición en la que la red dice que debería estar, luego interpola lentamente la entidad visible local hacia la sombra con el tiempo.
Incluí muchos detalles sobre este enfoque en mi respuesta anterior aquí
fuente
He escrito un artículo que detalla un enfoque ligeramente diferente, que produce resultados muy suaves: http://www.gabrielgambetta.com/fpm3.html
fuente