2011-04-17 13 views
9

Estoy haciendo un juego de estilo servidor MMO. Hasta ahora tengo el marco configurado para que el servidor y los clientes interactúen entre ellos para proporcionar actualizaciones de estado. El servidor mantiene el estado del juego y periódicamente calcula el siguiente estado y luego de vez en cuando (cada milisegundos) envía el nuevo estado a todos los clientes. Este nuevo estado puede ser visto y reaccionado en el lado del cliente por el usuario. Estas acciones luego se envían nuevamente al servidor para ser procesadas y enviadas para la próxima actualización.Sincronización del estado del juego Cliente-Servidor

El problema obvio es que lleva tiempo que estas actualizaciones viajen entre el servidor y los clientes. Si un cliente actúa para atacar a un enemigo, para cuando la actualización haya regresado al servidor, es muy posible que el servidor haya progresado el estado del juego lo suficiente como para que el enemigo ya no esté en el mismo lugar y fuera de alcance.

Para combatir este problema, he intentado encontrar una buena solución. He visto lo siguiente, y ha ayudado a algunos, pero no completamente: Mutli Player Game synchronization. Ya llegué a la conclusión de que, en lugar de simplemente transmitir el estado actual del juego, puedo transmitir otra información, como la dirección (o la posición del objetivo para el movimiento AI) y la velocidad. A partir de esto, tengo parte de lo que se necesita para 'adivinar', en el lado del cliente, cuál es el estado real (como lo ve el servidor) al avanzar el estado del juego n milisegundos hacia el futuro.

El problema es determinar la cantidad de tiempo para progresar en el estado, ya que dependerá del tiempo de demora entre el servidor y el cliente, que podría variar considerablemente. Además, si avanzo el estado del juego a lo que sería actualmente cuando el cliente lo visualiza (es decir, solo cuenta el tiempo que tardó la actualización en llegar al cliente) o debería progresar lo suficiente para que cuando se envíe su respuesta de vuelta al servidor, será el estado correcto para entonces (cuenta para ambos viajes).

¿Alguna sugerencia?

Reiterar:

1) ¿Cuál es la mejor manera de calcular la cantidad de tiempo entre la emisión y recepción?

2) ¿Debo avanzar el estado del lado del cliente lo suficiente como para contar para el viaje de ida y vuelta completo, o simplemente el tiempo que lleva obtener los datos del servidor al cliente?

EDIT: Lo que he encontrado hasta el momento

Puesto que ya tienen muchos paquetes que van y vienen entre los clientes y el servidor, no quiero añadir a ese tráfico si tengo que hacerlo. Actualmente, los clientes envían paquetes de actualización de estado (UDP) al servidor ~ 150 milisegundos (solo si algo ha cambiado), y luego estos son recibidos y procesados ​​por el servidor. Actualmente, el servidor no envía ninguna respuesta a estos paquetes.

Para comenzar, haré que los clientes intenten estimar su tiempo de retraso. Lo predeterminaré a algo así como 50 a 100 milisegundos. Propongo que cada 2 segundos (por cliente) el servidor responda inmediatamente a uno de estos paquetes, devolviendo el índice del paquete en un paquete de actualización de tiempo especial. Si el cliente recibe el paquete de tiempo, usará el índice para calcular cuánto tiempo hace que se envió este paquete, y luego usar el tiempo entre paquetes como el nuevo tiempo de retraso.

Esto debería mantener a los clientes razonablemente actualizados en su retraso, sin exceso de tráfico de red.

¿Sonido aceptable, o hay una manera mejor? Esto todavía no responde a la pregunta dos.

Respuesta

2

2) ¿Debo avanzar el estado del lado del cliente lo suficiente como para contar para todo el viaje de ida y vuelta, o simplemente el tiempo que lleva obtener los datos del servidor para el cliente?

Vamos a suponer que el servidor envía el estado en el instante T0, el cliente ve en el tiempo T1, el jugador reacciona en el tiempo T2, y el servidor obtiene su respuesta en el tiempo T3, y la procesa al instante. Aquí, el retardo de ida y vuelta es T1-T0 + T3-T2. En un mundo ideal, T0 = T1 y T2 = T3, y el único retraso entre el tiempo de observación y el procesamiento de la acción del jugador es el tiempo de reacción del jugador, es decir, T2-T1. En el mundo real es T3-T0. Así que con el fin de simular el mundo ideal que necesita para restar todo el retardo de ida y vuelta:

T2-T1 = T3-T0 + (T1-T0 + T3-T2) 

Esto significa que un jugador en una red más lenta ve el estado más avanzado a un jugador en una red rápida. Sin embargo, esto no es una ventaja para ellos, ya que lleva más tiempo hasta que se procesa su reacción. Por supuesto, podría ser divertido en el caso de dos jugadores sentados uno junto al otro y usando redes de velocidad diferentes. Pero este es un escenario bastante improbable, ¿no?

Existe un problema con todo el procedimiento: Está extrapolando en el futuro y esto puede provocar situaciones sin sentido. Algunos de ellos, como bucear en las paredes se pueden evitar fácilmente, pero los que dependen de la interacción del jugador no pueden.

Tal vez usted podría convertir su idea al revés: En lugar de previsión, intenta evaluar la actuación de un jugador en el tiempo T3 - (T1-T0 + T3-T2). Si determina que un personaje sería golpeado de esta manera, reduzca sus puntos de golpe en consecuencia. Esto puede ser más fácil y más realista que la idea original, o puede ser peor o no aplicarse en absoluto. Solo una idea.


imaginar dos jugadores corriendo uno contra el otro. Según la extrapolación, se cruzan en el lado derecho. De hecho, uno de ellos cambia su dirección, y al final se cruzan en el lado izquierdo.

+0

"Pero este es un escenario bastante improbable, ¿no?" ¿Qué ocurre si un dispositivo está utilizando una conexión celular y el otro está utilizando wifi? Solo un pensamiento. De cualquier manera, usted está diciendo que le muestre al usuario el estado en el que estará el juego cuando llegue la respuesta al servidor, ¿correcto? –

+0

* "conexión celular y wifi" *: normalmente, ambos intentarían usar la conexión más rápida. Podrían tratar de hacer trampa de esta manera, pero me parece un poco complicado. Sería una especie de trampa, pero en MMO hay formas mucho más fáciles de hacer trampa. – maaartinus

+0

Y sí, estaba diciendo esto. Ahora estoy agregando, que podría reducir la diferencia de tiempo en una pequeña constante para todos los jugadores. Menos extrapolación podría significar menos problemas; solo una idea. – maaartinus

4

En primer lugar, al igual que un FYI, si te estás preocupando por retrasos de menos de 1 segundo, estás comenzando a salir del reino del retraso realista para un MMO. La forma en que todos los grandes MMO manejan esto es básicamente teniendo dos "juegos" diferentes al mismo tiempo: hay un motor de juego subyacente que maneja todos los estados matemáticos, de carácter, aplicando los cambios numéricos, y luego está el cliente gráfico

El primer "juego", las matemáticas y los cálculos, están mucho más conceptualmente relacionados con un juego de consola tradicional (como los viejos MUD). Piense en términos de mensajes que van y vienen, con un alto grado de aislamiento de ACID. Estos mensajes se preocupan mucho más por la precisión, pero debe suponer que pueden tardar de 1 a 2 segundos (o más) en procesarse y actualizarse. Este es el "abogado de reglas" que garantiza que los puntos de ataque se calculen correctamente, etc.

El segundo "juego" es el cliente gráfico. Este cliente está realmente enfocado en mantener la ilusión de que las cosas están sucediendo mucho más rápido que el primer juego, pero también sincronizando los eventos que están llegando con la apariencia gráfica. Este cliente gráfico a menudo simplemente inventa cosas que no son críticas.Este cliente es responsable de los gráficos de 30 fps +. Es por eso que muchos de estos clientes gráficos usan trucos como iniciar la animación de ataque cuando el usuario presiona el botón, pero no resuelven la animación hasta que el primer juego soluciona el ataque.

Sé que esto es un poco fuera de la interpretación literal de su pregunta, pero una vez que fuera de dos máquinas sentados uno junto al otro en un 100 ms red es muy optimista ...

+0

Acepto que no puedo depender del tiempo de demora en milisegundos, pero sí necesito saber de qué se trata. –

+0

Sea cuidadoso al permitir que el cliente llegue a los cálculos: eso hace que los tramposos puedan burlar fácilmente a los clientes con éxito automático. –

+1

No dejo que el cliente haga esos cálculos, solo animaciones. –

2

Una forma de resolver este tipo de problema es ejecutar la simulación del juego en el cliente y el servidor.

Entonces, en lugar de simular el mundo solo en el servidor, hágalo en el cliente también. Simplemente envíe lo que el cliente hizo (por ejemplo, "jugador golpeó al monstruo") al servidor. El servidor ejecuta la misma simulación y verifica los eventos.

Si no coinciden (jugador haciendo trampa, rezagos), envía un veto al cliente y la acción no se registra como exitosa en el servidor. Esto significa que todos los demás clientes no lo notan (el servidor no reenvía la acción a los otros clientes).

Esa debería ser una forma bastante eficiente de manejar el retraso, especialmente si tienes muchas batallas PvM (en lugar de PvP): Dado que el monstruo es una simulación, no importa si hay un retraso largo entre el cliente y el servidor.

Dicho esto: la mayoría de las redes son tan rápidas que el desfase debería ser de unos pocos milisegundos. Eso significa que "solo" tiene que hacer que el servidor sea lo suficientemente rápido para que pueda responder, por ejemplo, < 100ms y los jugadores no lo notarán.

Cuestiones relacionadas