Entrada del lado del servidor

9

Actualmente en mi juego, el cliente no es más que un renderizador. Cuando se cambia el estado de entrada, el cliente envía un paquete al servidor y mueve al jugador como si estuviera procesando la entrada, pero el servidor tiene la última palabra sobre la posición.

Esto generalmente funciona muy bien, excepto por un gran problema: caerse de los bordes. Básicamente, si un jugador camina hacia un borde, digamos un acantilado, y se detiene justo antes de salir del borde, a veces un segundo después, será teletransportado fuera del borde. Esto se debe a que el paquete "Dejé de presionar W" se envía después de que el servidor procesa la información.

Aquí hay un diagrama de retraso para ayudarlo a comprender lo que quiero decir: http://i.imgur.com/Prr8K.png

Podría enviar un paquete "W Presionado" a cada trama para que el servidor lo procese, pero eso parece ser una solución costosa para el ancho de banda.

Cualquier ayuda es apreciada!

Thomas
fuente

Respuestas:

5

Si bien el servidor tiene la última palabra sobre la posición, debe hacerlo verificando y verificando lo que el cliente envía como entradas y posición. Digo esto porque lo que estás haciendo es mover al jugador inmediatamente y la expectativa que crea en tu código es que el cliente es la posición real.

Crees que generalmente funciona bien, pero no lo es. Nota al margen: usted dice que su cliente no es más que un renderizador, luego le da rápidamente el control local para moverse sin mensajes del servidor. No puede tener las dos cosas, espere a que el servidor le indique que se mueva o asuma cierto control sobre su posición y use el servidor para verificar trampas.

¿Noto que sus respuestas están llegando a un segundo entero? Esa es una latencia de 500 ms que es ridículamente grande para cualquier tipo de juego de acción. Trate de averiguar por qué este cambio está tomando tanto tiempo, podría ser cualquier cosa, desde las colas de comando que retroceden hasta que no se manejen rápidamente hasta el ancho de banda inundado o incluso demonios que causan muchos paquetes perdidos.

Lo que creo que debería pasar es que

client sends a move + position update
server gets it t+latency time later
server verifies and sends out info to all clients
client receives this at (t+latency + latency)

La parte difícil aquí es que si un cliente recibe un mensaje sobre sí mismo, debe ignorarlo a menos que ese mensaje sea algo así como "movimiento no válido, vaya a XYZ en su lugar". Si ese mensaje es para el cliente de otra persona sobre el que está obteniendo información, entonces tendrá que extrapolar los reenvíos a tiempo para que parezca estar donde estará.

Patrick Hughes
fuente
El cliente no envía su posición en absoluto; simplemente predice / interpola. Es por eso que se cae cuando cree que está en el borde. Además, no veo dónde dije que el retraso fue de 1 segundo, es más como 8 ms (prueba local) a 100 ms (a través de Internet). Dije que el jugador se estaba retrasando más tarde porque periódicamente envío actualizaciones de posición completas. ¿Estoy en lo cierto al entender que debo enviar la posición que el cliente cree que debería ser, junto con las teclas que se presionaron, y el servidor debe verificar si es posible?
Thomas
"a veces un segundo después, será teletransportado" implicaba los grandes retrasos, que es de donde obtuve el tiempo. Para un juego de acción receptivo, sí, el cliente juega y el servidor juega a tiempo y le informa al cliente si ha hecho algo ilegal. Notarás que en los juegos multijugador en línea, en su mayoría, ves a otras personas cambiar de posición (las que provienen del servidor), mientras que tu propia posición solo rara vez cambia de las correcciones directas del servidor. Otras personas te ven cambiar de posición, etc ...
Patrick Hughes
Sin embargo, ¿no podría esto causar que el jugador se caiga del servidor? A menos que envíe un paquete cada cuadro, el servidor aún podría pensar que el reproductor se está moviendo durante unos 32 ms. (Solo envío paquetes cada tres cuadros). ¿O sugiere que no simulo ninguna entrada en el servidor, sino que solo verifico si la posición está dentro de los límites de la entrada presionada?
Thomas
Dado que el servidor solo corrige los movimientos no válidos informados por el cliente, nunca enviaría un mensaje "usted se cayó del precipicio" a menos que el cliente mismo se saliera del límite. En este ciclo de retroalimentación, es el servidor el que se corrige a sí mismo a la visión del mundo del cliente y su lugar en él. El movimiento se sentirá nítido y receptivo para el jugador. Otras acciones, como interactuar con objetos del mundo, implicarán esperar a que el servidor le diga al cliente lo que acaba de suceder, haga clic en un cuadro y espere respuesta, pero aquí solo estamos hablando de movimiento.
Patrick Hughes el
Eso se parece mucho a lo que estoy haciendo actualmente; enviando una posición al servidor y haciendo que el servidor valide si el jugador podría haberse movido a esa posición. Sin embargo, parece ser un enfoque más heurístico y, en mi opinión, no sería tan efectivo como hacer que el servidor decida, punto. ¿Funcionaría el envío de marcas de tiempo con cada paquete? Creo que eso erradicaría el problema. Creo que Halo y los juegos que usan el motor Source usan eso.
Thomas
0

Entiendo tu pregunta como:

El servidor recibe un paquete cuando comienzo a presionar el botón "reenviar" y otro paquete cuando finalmente suelto el botón "reenviar". Por lo tanto, el movimiento real en el servidor comienza y termina aproximadamente 100 milisegundos 'demasiado tarde' en el juego real frente a lo que el jugador está expresando en el lado del cliente. Entonces, si el jugador quiere moverse 10 segundos, puede terminar moviéndose 10.x segundos en lugar de estar en x >= 1línea.

Esta es una mala estrategia de diseño porque no expresa la voluntad del jugador en el mundo del juego como el jugador pretende, creando una experiencia de usuario bastante pobre.

La solución que recomendaría es enviar un paquete (tan a menudo como sea posible) que indique cuántos pasos tomó el jugador y en qué dirección. El servidor luego actualiza el mundo del juego con la nueva ubicación del jugador si pasa una verificación de corrección. Por lo tanto, el jugador puede moverse con gran precisión y evitar caerse de las repisas altas.

La alternativa sería recordar las posiciones del jugador en el último segundo y corregir la posición en retrospectiva al momento en que se soltó el botón. Parece que crearía ese efecto de banda elástica de los viejos tiempos (solo por una razón diferente)

Básicamente, debería enviar un paquete de qué botón se presionó y cuál fue la hora real del juego en que se presionó el botón y luego, qué botón se soltó y en qué momento exacto.

AturSams
fuente
Como le dije a Patrick, creo que la solución sería más un enfoque heurístico; en lugar de que el servidor sea "The Man", el servidor verifica la validez de los datos del cliente. Esto, por supuesto, tendrá que crear un margen de maniobra para que el retraso u otros problemas de red no creen falsos positivos.
Thomas