Interpolar posiciones en un juego multijugador


14

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ó.


Hola Ivo Creo que este es un buen tema, pero no está claro qué está haciendo su código, por ejemplo, ¿de dónde provienen serverCurrentPosition, serverNextPosition, timeBetweenTicks?
CiscoIPPhone

Eso es enviar los datos de actualización que provienen del servidor.
Ivo Wetzel el

Respuestas:


11

Tienes nerviosismo, porque el retraso está cambiando constantemente. Esto significa que, si bien el servidor envía actualizaciones exactamente cada timeBetweenTickstic, el cliente las recibe después de un tiempo variable. Es probable que ese tiempo esté cerca de timeBetweenTicksuna 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.


Ya es así, que los objetos no se detienen, continúan avanzando hasta que reciben la próxima actualización. Además, el uso de Aceleración de hardware en el lienzo HTML parece reducir bastante el efecto de fluctuación. Tal vez me volví loco después de trabajar en eso durante tanto tiempo.
Ivo Wetzel el

Eso es muy posible. Si activar la aceleración aumenta la velocidad de fotogramas, entonces aumenta la probabilidad de manejar la información de actualización en el momento exacto.
importa

9

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í


Hm, hice algo así en una versión anterior, la imprecisión de coma flotante lo hizo realmente malo a veces, tengo períodos de tiempo bastante grandes entre las actualizaciones, hasta 300 ms para algunos objetos, pero tal vez lo hice mal, lo voy a dar una oportunidad cuando encuentro algo de tiempo libre :)
Ivo Wetzel

¡la precisión de punto flotante realmente no debería entrar en esto en absoluto! ¿Leíste mi respuesta vinculada en stackoverflow? Cubre todos los detalles de la implementación de este tipo de cosas.
Martin

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.