¿Qué enviar al servidor en tiempo real del juego FPS?

23

¿Cuál es la forma correcta de comunicar la posición de nuestro jugador local al servidor? Algunos documentos dicen que es mejor enviar las entradas cada vez que se producen. Y algunos documentos dicen que el cliente envía su posición en un intervalo fijo.

Con el enfoque de envío de entradas: ¿Qué debo hacer si el jugador mantiene presionadas las teclas de dirección? Significa que necesito enviar un paquete al servidor en cada marco. ¿No es demasiado? Y también está la rotación del jugador desde la entrada del mouse. Aquí hay un ejemplo:

http://www.gabrielgambetta.com/fpm_live.html

¿Qué pasa con el envío de la posición en enfoque de intervalo fijo? Envía muy pocos mensajes al servidor. Pero también reduce la capacidad de respuesta.

Entonces, ¿qué camino es mejor?

syloc
fuente

Respuestas:

19

Respuesta simple: ¡engaña o no seas tan preciso!

Si has jugado algún juego de disparos en línea, lo más probable es que hayas experimentado la llamada "banda de goma" si tu conexión con el servidor es mala.

Esto es causado por su cliente corrigiendo su posición de vez en cuando.

Básicamente, lo que sucede en los dos lados:

  • El servidor rastreará su movimiento y enviará actualizaciones a los clientes como se esperaba. Estas no siempre tienen que ser actualizaciones completas. Cada x cuadros puede haber una actualización completa, todos los demás cuadros solo envía nuevos vectores de velocidad (si hay algún cambio).

  • Su propio cliente le permitirá moverse libremente, pero utilizará las actualizaciones proporcionadas por el servidor para corregir / ajustar su posición. Esto asegurará que el juego se sienta receptivo, incluso si no actualiza la posición cuadro por cuadro.

Pero, ¿cómo se maneja la entrada? Su cliente enviará su posición al servidor "Me mudé allí". El servidor verificará esta actualización (por ejemplo, ¿debería poder moverse allí tan rápido?) Y si es válida, muévase (o rechace su actualización, lo que da como resultado "bandas de goma").

Entonces sí, su enfoque de intervalo fijo probablemente funcionará y será suficiente.

Pero incluso si desea enviar información y manejar el movimiento en ambos lados, tenga en cuenta que no tiene que enviar "el botón todavía está presionado". En su lugar, envíe un evento cuando se presiona el botón y otro una vez que se suelta el botón.

Mario
fuente
55
Sí, puedo seguir la presión y soltar el botón. ¿Pero qué pasa con la entrada del mouse? Está cambiando constantemente.
syloc
66
"En cambio, envíe un evento cuando se presiona el botón y otro una vez que se suelta el botón". - Es cierto, pero es necesario que se realicen verificaciones para asegurarse de que el evento "en el lanzamiento" se forza eventualmente, dependiendo de las reglas de los juegos. Por ejemplo, en el modo multijugador Rainbow Six Vegas 2 , un jugador puede comenzar a disparar su arma, y ​​un error (desafortunadamente común) hace que el mensaje "deje de disparar" no llegue con éxito al servidor. Esto da como resultado que el audio de disparo permanezca en un bucle infinito durante el resto del partido. Solo un ejemplo para tener cuidado. youtu.be/GOQIbLCy7m8?t=9m10s
Mike Baxter
@syloc: solo maneje el lado del cliente y deje que el servidor determine si el movimiento es válido / posible (para evitar cosas como hacks de teletransporte y similares).
Mario
@syloc Solo establezca un intervalo para el mouse, pero para ahorrar ancho de banda adicional aún haga una verificación del lado del cliente para ver si ha cambiado. Si hay un período de tiempo sin movimiento del mouse, no necesita seguir enviando mensajes al respecto.
agosto
En uno de mis trabajos, teníamos un ingeniero que prácticamente se volvía loco optimizando el comportamiento de primavera para las actualizaciones de posición perdidas para el acceso telefónico (hace 13 años). Ahora veo juegos con mucho ancho de banda y ridículamente baja latencia que sufren este problema, parece que el problema nunca desaparecerá o que a la gente le importa mucho menos en estos días.
Andon M. Coleman
5

Si aún no lo ha hecho, le sugiero que lea estos dos artículos profundos pero comprensibles: https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking y http://fabiensanglard.net/quake3/network.php .

Estos explican por qué se recomienda utilizar el envío de paquetes de 'intervalo fijo'. Para ser breve, de hecho, es principalmente importante para los paquetes enviados por el servidor.

El envío de un paquete tiene un costo fijo, y el tamaño máximo de un paquete de red es de aproximadamente 1.5 KB. Entonces, si tiene, por ejemplo, 16 jugadores en su servidor, cada cuadro cuando calcule el movimiento de un jugador, el código ingenuo podría enviar un paquete de actualización a cada jugador después de cada resolución de movimiento, por lo que 16 * 16 = 256 paquetes. Si tiene un framerate de 30, eso es 7680 paquetes.

Un mejor enfoque es crear un búfer en cada inicio del cuadro, concatenar en él la actualización de sus 16 posiciones calculadas y luego enviarlas a sus 16 jugadores.

Ahora envía solo 480 paquetes por segundo para obtener los mismos resultados.

En el caso de jugador a servidor, eso solo significa que debe enviar, en el mismo paquete, un máximo de datos, como; posición buscada, acciones llamadas este marco y así sucesivamente.

Acerca de la segunda parte de su pregunta: la forma en que elegí reducir la sensación de retraso fue enviar esta información al servidor en cada cuadro:

  • posición actual real del jugador (utilizada por el servidor para verificar si las posiciones del lado del servidor y del lado del jugador no están demasiado desincronizadas).

  • Posición estimada del jugador en 1 segundo: calculada por el cliente: si el jugador no cambia la dirección del mouse y deja el teclado en su estado actual durante 1 segundo, ¿dónde estará el jugador? (no nos importan las colisiones) Si el jugador no se mueve, su posición estimada en 1 segundo es su posición actual.

  • La posición que mira.

Cada vez que el servidor recibe esta información, actualiza la posición futura y la posición buscada, y la entidad del jugador finalmente se mueve hacia su posición futura.

Los jugadores nunca se sincronizan exactamente, pero la respuesta de entrada es instantánea (lo más importante para mí) y descubrí que las posiciones predichas son lo suficientemente precisas para mí.

GaelFG
fuente
"Los jugadores nunca se sincronizan exactamente" Creo que también es importante mencionar que el nivel de precisión aquí depende del juego (juego) real. Por ejemplo, un MMO clásico en el que simplemente haces clic y seleccionas entidades, no necesitará una precisión perfecta para casi todo, pero en un tirador, la sincronización de buena a perfecta es esencial.
Mario
La cosa es que nadie en su sano juicio usa TCP para un FPS. Prefieren lidiar con una secuenciación complicada y datagramas perdidos que incurrir en la sobrecarga de TCP.
Andon M. Coleman