Estoy implementando un clon de asteroides multijugador para aprender sobre la arquitectura de red cliente / servidor en los juegos. He pasado tiempo leyendo las publicaciones de GafferOnGames y Valve sobre la tecnología de su cliente / servidor. Tengo problemas con dos conceptos.
Actualmente tengo un servidor de juegos autorizado que simula la física con box2d y envía el estado del mundo a los clientes aproximadamente 20 veces por segundo. Cada cliente realiza un seguimiento de las últimas instantáneas que recibió y salta entre dos estados para suavizar el movimiento de los sprites. Sin embargo, no es tan suave. Puede ser suave por un tiempo, luego un poco irregular, luego volver a ser suave, etc. He intentado tanto TCP como UDP, ambos son casi lo mismo. ¿Alguna idea de cuál podría ser mi problema? (Nota: Primero implementé esto para un solo jugador, y el movimiento del sprite es perfectamente suave a 60 fps cuando actualizo el mundo de la física solo 20 veces por segundo).
Para resolver el primer problema, pensé que tal vez el cliente también debería ejecutar una simulación box2d y simplemente actualizar las posiciones de sus sprites para que coincidan con las instantáneas del servidor cuando no coinciden. Pensé que esto podría ser más sencillo ya que mi implementación para un solo jugador es fluida. ¿Es esta una buena idea?
Incluso si no soluciona el problema anterior, ¿es necesario para la predicción del lado del cliente? Por ejemplo, si un jugador intenta mover su nave, ¿cómo sabrán si chocan contra un asteroide, una pared o una nave enemiga sin una simulación física? Parece que su nave parece pasar a través del objeto con el que debería colisionar antes de recibir una instantánea del servidor que dice que golpeó el objeto.
¡Gracias!
fuente
+-*/
El comportamiento de IEEE 754 binary32 floats [..] está estrictamente definido para operaciones como " es completamente falsa. Todas esas operaciones en IEEE-754 podrían variar según la implementación. Vea aquí y aquí para más información.Probablemente no se vea tan bien ya que la interpolación entre ellos depende de tener siempre el siguiente conjunto de datos para interpolar. Esto significa que, si hay un pico de retraso corto, todo tiene que esperar para ponerse al día.
Hay un artículo antiguo en GameDev sobre el uso de splines cúbicos para predecir la posición de un objeto más allá del punto donde tuvo los últimos datos. Lo que debe hacer es usar esa posición y luego ajustar la spline cuando obtenga nuevos datos para contabilizar su nueva posición. También es probablemente mucho más barato que ejecutar una segunda simulación de física, y significa que no tiene que decidir en quién confía, ya que ha implementado explícitamente el cliente que lo inventa a medida que avanza. :)
fuente
He hecho algunas cosas similares yo mismo, y ejecuté Box2D solo en los clientes. La forma en que lo hice fue dejar que el cliente ejecutara su propia simulación prácticamente por sí mismo, enviando la velocidad actual (y la rotación) en cada paquete de sincronización al servidor. El servidor luego envía esta información a otros jugadores, que establecen las velocidades recién recibidas en las entidades replicadas. Fue muy suave, sin diferencias notables entre los clientes.
Por supuesto, el problema aquí es que no hay un control centralizado sobre las entidades, pero creo que eso también podría hacerse en el lado del servidor haciendo una simulación del lado del servidor de la física.
fuente
Personalmente, preferiría ejecutar las simulaciones solo en el servidor y hacer que transmita cualquier cambio en las velocidades / aceleraciones lineales / angulares de los objetos involucrados siempre que sucedan. Es, cuando un determinado objeto, por cualquier motivo, cambia cualquiera de sus propiedades físicas (como las velocidades y aceleraciones mencionadas anteriormente), este cambio específico se enviará del servidor al cliente, y el cliente cambiará su lado del datos del objeto en consecuencia.
La ventaja de esto sobre su implementación actual es que anulará la necesidad de interpolaciones del lado del cliente y generará un comportamiento muy fiel en los objetos. El problema es que este método es bastante vulnerable a las latencias, que se convierten en un gran problema cuando los jugadores están geográficamente demasiado lejos el uno del otro.
En cuanto a la pregunta 1, digo que el problema sería fluctuaciones en la latencia, porque no hay garantía absoluta de que haya un intervalo de 20 segundos exactamente perfecto entre cada recepción de la instantánea. Permítanme ilustrar (siendo "t" el tiempo medido en milisegundos):
1) En t = 20 desde el inicio del juego, el cliente recibió una instantánea e hizo la interpolación con éxito y sin problemas.
2) En t = 40, hubo una latencia entre el servidor y el cliente, y la instantánea solo llegó a t = 41.
3) En t = 60, el servidor envió otra instantánea, pero un segundo de la simulación se desperdició en el cliente debido a la latencia. Si la instantánea llega a t = 60, el cliente no hará una interpolación de los instantes 40 y 60, sino de los instantes 41 a 60, generando un comportamiento diferente. Esta inexactitud podría ser la causa de la eventual "sacudida".
En cuanto a la pregunta 2, su idea podría funcionar si implementa algo que rastree de manera eficiente si cada objeto está realmente sincronizado cliente-servidor sin tener que enviar paquetes a cada cuadro informando la posición de los objetos. Incluso si lo hace a intervalos discretos, no solo se ejecutará en el mismo problema de la pregunta 1, sino que también tendrá cantidades demasiado grandes de datos para transferir (lo cual es algo malo).
fuente