Sincronizar clientes con un servidor y entre ellos

9

¿Cuál es la mejor manera de mantener todos los clientes sincronizados con un servidor y entre ellos?

Actualmente, tenemos dos enfoques en mente:

  1. Cuando un cliente envía algo al servidor, el servidor envía inmediatamente mensajes a todos los clientes, que reaccionan de inmediato.
  2. Introduciendo algún retraso de tiempo, mediante el cual el servidor envía mensajes a todos los clientes, con la directiva, "actúe sobre esto a tiempo t.

El segundo enfoque parece que probablemente mantendría a todos los clientes en una mejor sincronización (ya que ofrece cierto grado de retraso); pero me pregunto si la capacidad de respuesta se perdería en un grado demasiado alto (es decir, el usuario hace clic en "saltar" y hay una brecha notable entre presionar el botón y realmente saltar).

También existe la posibilidad de que los clientes calculen su propia posición (y no esperen a que los servidores digan "has saltado"); pero debido al retraso inevitable, los clientes estarían muy desincronizados.

Luego está toda la pregunta TCP vs. UDP; porque lo queremos rápido, pero también odiaría que el servidor diga que estás en una ubicación completamente diferente de lo que pensabas.

Con todas estas demandas en competencia, todo se vuelve muy incierto sobre cómo debemos abordar este problema. ¿Cuál de estos enfoques (o cualquier otro) sería mejor para mantener sincronizados a los clientes y al servidor? ¿Cuáles se usan realmente en la industria?

Smashery
fuente

Respuestas:

7

La respuesta rápida es: no hay mejor enfoque.

Todos los juegos contienen arquitectura diferente; cada juego elegirá diferentes conjuntos de datos para enviar con el fin de sincronizarse con otras máquinas, lo que afectará las elecciones que puede hacer al elegir cómo lidiar con el retraso.

Lo que especifique en la opción n. ° 2: que los clientes envíen mensajes para actuar en el futuro, es definitivamente un enfoque. De hecho, el motor de origen utiliza una variante de este enfoque , donde la representación siempre está a 100 ms de las acciones locales del cliente; Todas las máquinas intentan operar en las mismas acciones al mismo tiempo. Esto agrega un retraso artificial e imperceptible al juego para ocultar la latencia real de la red.

Si no puede adoptar este enfoque, también puede elegir la opción n. ° 1, simplemente enviando los datos más actualizados y, una vez recibida, utilice la interpolación y la extrapolación (predicción del lado del cliente) para tratar de ocultar la latencia. He utilizado este enfoque en al menos un juego de envío, pero de nuevo, todo depende de tu juego; Puede haber otros enfoques que puede tomar.

Finalmente, al elegir entre TCP y UDP, probablemente desee UDP. Hay escenarios en los que TCP es una opción viable para conectar en red su juego, pero cuando está creando un juego de acción, desea obtener los datos más recientes lo antes posible. Si puede manejar paquetes descartados usted mismo, UDP es la mejor opción. (Hay bibliotecas, como ENet , que proporcionan un contenedor alrededor de UDP para reemplazar la funcionalidad de TCP, como paquetes confiables).

Blair Holloway
fuente
Realmente no quieres usar UDP. La sobrecarga de una conexión TCP configurada correctamente es mínima y el infierno que es la entrega fuera de orden es algo que nadie debería tener que vivir.
coderanger
2
No es una cuestión de gastos generales, aunque TCP agrega algo: la forma en que TCP trata con los paquetes descartados no es fundamental en los juegos en los que una gran latencia entre acción y reacción puede marcar una gran diferencia en la jugabilidad. Para un juego como WoW, donde las acciones son relativamente poco frecuentes, TCP funciona, pero se caería en un juego como CounterStrike, ya que un solo paquete descartado acelerará su conexión y potencialmente lo hará "retrasarse" por un segundo o más.
Blair Holloway
Si va a usar UDP, realmente es mejor no escribirlo usted mismo; use un envoltorio como ENet que haga el trabajo duro por usted. Pero mi respuesta original sigue en pie: UDP es la mejor manera de hacerlo si estás haciendo un juego con algún tipo de acción acelerada.
Blair Holloway
Para mí, RakNet hizo que ejecutar una conexión UDP para mi motor de juego fuera extremadamente fácil. Tiene muchas opciones sobre cómo desea enviar su paquete, es decir. cómo ordenarlos, si el paquete se reenvía si se cae, etc.
BarakatX2
3

Aquí hay un par de buenos enlaces que cubren una gran cantidad de redes de juegos.

Y esta es la primera parte de la serie de redes más prácticas. http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/

Por la historia. 'lo sentimos, pero como mecanismo de prevención de spam, los nuevos usuarios solo pueden publicar un máximo de un hipervínculo. Gana 10 reputación para publicar más hipervínculos. Solo mire alrededor de su sitio web, de todos modos.

jsimmons
fuente
1

Como menciona Clientes y Servidores, voy a suponer que está hablando de una arquitectura Cliente / Servidor en la que el Servidor es la autoridad en el estado de todos los objetos.

Nota: La alternativa es una arquitectura punto a punto donde el propietario de un objeto es la autoridad para ese objeto.

Ya existe un método bien probado para sincronizar objetos en movimiento utilizando la arquitectura Cliente-Servidor. Se llama Dead Reckoning. .

Una buena manera de implementar esto en un juego sería así:

  1. Los clientes envían entradas al servidor.
  2. El servidor actualiza los objetos del juego (aceleraciones y direcciones) y los envía de vuelta a los Clientes.
  3. Los clientes usan estos valores actualizados para simular el movimiento de los objetos localmente.
  4. Ocasionalmente, el servidor envía una corrección de posición para evitar la deriva.
  5. Enjuague; repetir.
JanSolo
fuente