c# - tutorial - Sincronización de juegos multijugador
juegos sencillos en c# (5)
El enfoque básico para esto es algo llamado Dead Reckoning y aquí se puede encontrar un artículo bastante bueno sobre él. Básicamente, se trata de un algoritmo de predicado para determinar las posiciones de las entidades para los tiempos entre las actualizaciones del servidor.
Existen metodologías más avanzadas que se basan en este concepto, pero es un buen punto de partida.
También se puede encontrar una descripción de cómo se maneja esto en el motor de origen (motor de Valve para el primer juego de Half Life), el principio es básicamente el mismo, hasta que el servidor le indique que use un algoritmo de predicción para mover la entidad a lo largo de un ruta esperada, pero este artículo maneja el efecto que esto tiene al tratar de filmar algo con más profundidad.
Tengo una arquitectura de servidor / cliente implementada, donde todos los cambios de estado se envían a la función, se validan y se emiten a todos los clientes conectados. Esto funciona bastante bien, pero el sistema no mantiene la sincronización entre las instancias del juego del cliente a partir de ahora.
Si ocurriera un retraso de 5 segundos entre el servidor y un cliente en particular, recibiría el cambio de estado 5 segundos después del resto de los clientes, dejándolo con el estado del juego fuera de sincronización. He estado buscando varias formas de implementar un sistema de sincronización entre los clientes pero hasta ahora no he encontrado mucho.
Soy nuevo en la programación de redes y no soy tan ingenuo como para pensar que puedo inventar un sistema funcional sin dedicarle una gran cantidad de tiempo. Las ideas que he tenido, sin embargo, es mantener algún tipo de sistema de tiempo, por lo que cada cambio de estado estaría conectado a una marca de tiempo específica en el juego. De esa forma, cuando un cliente recibe un cambio de estado, sabrá exactamente en qué período del juego ocurrió el cambio y, a su vez, podrá correlacionarse con el retraso. El problema con este método es que en esos segundos de retraso el juego habría continuado en el lado del cliente y, por lo tanto, el cliente tendría que retroceder a tiempo para actualizar el cambio de estado, lo que definitivamente sería complicado.
Así que estoy buscando artículos para debatir sobre los temas o los algoritmos que lo resuelven. Quizás todo mi diseño de cómo funciona el sistema multijugador es defectuoso, en el sentido de que la instancia del juego de un cliente no debería actualizarse a menos que se reciba una noción del servidor. En este momento, los clientes se actualizan en su bucle de juego suponiendo que ningún estado ha cambiado.
Los mejores recursos que he encontrado en esta área son estos dos artículos de Valve Software:
Nunca habrá una manera de garantizar una sincronización perfecta en múltiples puntos de vista en tiempo real: las leyes de la física lo hacen imposible. Si el sol explotara ahora, ¿cómo se podría garantizar que los observadores de Alpha Centauri vean la supernova al mismo tiempo que lo haríamos en la Tierra? La información toma tiempo para viajar.
Por lo tanto, sus opciones son modelar todo con precisión con latencia que puede diferir de espectador a espectador (que es lo que tiene actualmente), o modelarlos de forma inexacta sin latencia y sincronizados ampliamente entre los espectadores (que es donde predicción / estimación / extrapolación muertas en). Los juegos más lentos como la estrategia en tiempo real tienden a ir en la primera ruta, los juegos más rápidos van en la segunda ruta.
En particular, nunca debe suponer que el tiempo que lleva viajar será constante. Esto significa que el simple envío de mensajes de inicio y finalización para mover entidades nunca será suficiente en ninguno de los modelos. Debe enviar actualizaciones periódicas del estado real (generalmente varias veces por segundo para juegos más rápidos) para que el destinatario pueda corregir el error en sus predicciones e interpolaciones.
Si el cliente ve eventos que suceden a la velocidad que el servidor lo está alimentando, que es la manera normal de hacerlo (he trabajado con protocolos de Ultima Online, KalOnline y un poco de World of Warcraft), entonces este retraso de 5 segundos le haría recibir estos 5 segundos de eventos al mismo tiempo y vería esos eventos pasando muy rápido o casi instantáneamente, ya que otros jugadores lo verían "caminando" muy rápido por una distancia corta si sus salidas también se retrasan. Después de eso, todo fluye normalmente de nuevo. En realidad, a excepción de la normalización gráfica y física, no veo ninguna necesidad especial para sincronizarla correctamente, simplemente se sincroniza.
Si alguna vez jugaste juegos Valve en dos computadoras cercanas, te darás cuenta de que no les importan detalles menores como "el lugar exacto donde moriste" o "a donde volaron las piernas del cuerpo muerto". Todo depende del cliente y se ve totalmente afectado por la latencia, pero esto es irrelevante.
Después de todo, los jugadores rezagados deben aceptar su condición, o cerrar su maldito eMule.
Su mejor opción es enviar los cambios al cliente desde el futuro, llegando así al cliente en el mismo momento en que lo hace para otros clientes que no tienen problemas de demora.