Tengo los fundamentos de los sockets TCP, la comunicación UDP, etc., pero no puedo encontrar mucho sobre cómo aplicarlos a un entorno de juego en tiempo real.
Tengo un clon de Pong, con 4 jugadores, y necesito sincronizar las posiciones de pádel entre los tres clientes y el servidor (el servidor es el cuarto jugador). Actualmente uso UDP para enviar actualizaciones en tiempo real (movimientos de paleta) y TCP para configurar el lobby del juego, etc.
¿Es MALO enviar spam a grandes cantidades de tráfico UDP? ¿Debería buscar algo como DCCP por sus características de congestión? ¿O no es realmente un problema con un proyecto a pequeña escala como este?
¿Cuándo se deben enviar los mensajes de sincronización entre cliente / servidor? Actualmente, el servidor está enviando paquetes UDP con el estado actual del juego tan rápido como puede administrar, y los clientes están enviando su posición de paleta al servidor lo más rápido que pueden. ¿Es esta la mejor manera de hacerlo? ¿Hay algún tipo de retraso que deba agregar para que los mensajes se envíen una vez cada X milisegundos, o solo debería enviar mensajes a medida que ocurren los eventos? (por ejemplo, la velocidad de la paleta cambió debido a la entrada del usuario)
¿Sería mejor hacer que los clientes comuniquen sus posiciones de remo entre pares?
Estoy haciendo estas preguntas dentro del contexto de Pong, pero también estoy interesado en cómo se superarían estos problemas en otros juegos o soluciones generalizadas.
fuente
Respuestas:
Tenga un intervalo de actualización configurable (para que pueda ajustar y probar 5 paquetes por segundo o 20), y cada cuadro vea si es hora de enviar una actualización. Puede que estés bien con un juego simple que envía paquetes para cada evento, pero en un juego más complejo esto no es práctico. También tenga en cuenta que hay una sobrecarga de paquetes, por lo que si está enviando un montón de paquetes pequeños, perderá el ancho de banda.
Cada intervalo de actualización hace que cada cliente envíe su posición de paleta al servidor o a cada cliente (par-par). Haga que el servidor también envíe la posición de la pelota y un vector de velocidad. Cada cliente puede ejecutar el mismo código de dibujo de pantalla que en un jugador para que el movimiento de la pelota sea suave. En el modo multijugador, solo tiene que enviar el servidor las actualizaciones de posición / velocidad de la pelota a intervalos regulares (y si lo desea cada vez que golpea algo).
Haga que las actualizaciones de la posición de la pelota hagan referencia a un tiempo de juego en todos los clientes para que pueda descartar paquetes fuera de orden e incluso hacer que la interpolación de la posición de las bolas sea más precisa (usted conoce la posición y la velocidad en un momento específico en el pasado para que pueda interpolar el nuevo posición).
Con este modelo con un juego lento, puede ver la pelota moverse hacia atrás a veces o saltar un poco. Pero con una conexión decente, debería ser bastante suave.
fuente
Con respecto a las preocupaciones de tráfico: desea evitar enviar más de 20-30 paquetes por segundo por par. En el caso general, si envía paquetes más pequeños y menos, experimentará (ligeramente) menos latencia y una menor posibilidad de paquetes descartados.
Definitivamente no desea enviar actualizaciones a una velocidad más rápida que la velocidad de fotogramas, ya que los jugadores no podrán notar la diferencia; de hecho, si solo envía paquetes 10 veces por segundo e interpola / extrapola los resultados en el extremo receptor , la mayoría de los jugadores no notarán la diferencia.
fuente
Esta es una pregunta bastante amplia, pero intentaré resumir los aspectos importantes.
La primera decisión que debe tomar en el código de red para su juego es si desea una configuración de cliente / servidor de un acuerdo de igual a igual. La mayoría de los juegos, con RTS probablemente como la única excepción notable, probablemente estén usando una arquitectura cliente / servidor. La principal ventaja es que esta disposición es más tolerante a fallas y proporciona más control sobre los datos que recibe cada cliente. Peer to peer permite enviar muchos menos datos, pero requiere que cada par simule completamente el mundo con precisión, como lo hace cualquier otro par. Si un compañero se retrasa o desincroniza, todos deben esperar a que se recuperen o simplemente se pierden.
UDP es generalmente la opción correcta también, ciertamente para cualquier modelo de cliente / servidor. TCP podría ser práctico para un juego de igual a igual, pero incluso entonces UDP podría ser una mejor opción. Básicamente, UDP maneja menos para usted, lo que significa más esfuerzo pero también más control sobre cómo lidiar con las fallas.
Para Pong, la elección que haría sería cliente / servidor, ya que es un juego orientado a la acción. Una cosa a tener en cuenta aquí, a pesar de que usted dice que un jugador "es el servidor", es mejor estructurar su código de manera tal que esencialmente ejecute un servidor local y se conecte a él como cliente.
Definitivamente tampoco querrás enviar actualizaciones de "spam" en ninguna dirección. Una actualización del servidor por cuadro es todo lo que se necesita, y su servidor debe ejecutarse a una velocidad de cuadro fija. Depende de usted, pero no hay necesidad de exagerar. Un marco de 50 ms (20 FPS) es suficiente para obtener un buen juego sin problemas. Para mantener las cosas fluidas en el cliente, desea utilizar la interpolación. El cliente debe estar en constante transición entre las instantáneas de trama del servidor, sin embargo, este podría ser fácilmente el tema de una pregunta separada.
Las actualizaciones del cliente también deberían ser limitadas, aunque una por fotograma probablemente sea demasiado si su cliente se ejecuta a una velocidad de fotogramas decente.
fuente
¿Te importa hacer trampa?
Si no, ir de igual a igual reducirá a la mitad su retraso, ya que es A <-> C en lugar de A <-> B <-> C. Si es así, para lograr una sincronización justa, es posible que desee hacer que la respuesta sea algo lenta para el jugador local, o lo que hace la mayoría de los juegos: deje que el jugador haga lo que sea localmente y luego retroceda si el resultado del servidor difiere del simulado localmente.
Un clon de pong es realmente un poco complicado, porque a diferencia de la mayoría de los juegos no puedes hacer trampa (como desarrollador) haciendo que un lado vea un golpe y el otro no.
En cuanto a algo generalizado, una técnica de la que he oído hablar pero que no he encontrado necesaria (aunque puede ser para juegos de acción) es mantener las acciones con sus marcas de tiempo verdaderas (recibir tiempo - ping / 2) y hacer que el servidor retroceda ( complemento) si entra un evento anterior y luego vuelve a aplicar acciones posteriores. De esa manera, todos son consistentes localmente a menos que haya algún conflicto debido a las interacciones de los diferentes jugadores. El único peligro es la capacidad de "retroceder el tiempo" si fingen una conexión lenta.
fuente
Google estima muerto. Enviar actualizaciones para 4 jugadores no será significativo. La cantidad de datos enviados será del orden de bytes. Entonces, eso significa que las actualizaciones frecuentes deberían estar bien. Con un cálculo muerto, mueves el reproductor en el cliente y el servidor. El servidor es la autoridad. Cuando la posición del cliente se desvía demasiado de la sincronización del servidor, tiene que volver a alinearse. http://trac.bookofhook.com/bookofhook/trac.cgi/wiki/Quake3Networking Usar UDP es el camino a seguir. Los Bupdates se enviarán con frecuencia a los datos perdidos que pronto serán reemplazados por datos entrantes de todos modos. La retransmisión de paquetes de TCP no vale la pena para la posición del jugador. Consulte este artículo para obtener más información sobre cómo mantener sincronizados al cliente y al servidor.
fuente
He programado un juego de 2 jugadores de red local de ping pong hace unas semanas, así es como lo hice:
-Un lado abre un servidor, el otro se conecta automáticamente -están enviando spam sus paletas x posición hacia el otro a 60 fps o menos [UDP] -si un lado golpea la pelota, deciden sobre la nueva velocidad y posición de la pelota y la envían al otro [TCP] -si la pelota vuela más allá de una pala, el jugador que la perdió se pone en contacto con el otro con un mensaje de aumento de puntaje y la pelota se reinicia [TCP] -la pelota se simula de forma independiente todo el tiempo, lo que se adapta a la física de pelota simple de pong
Esto crea aproximadamente 0.3 a 0.5 KByte / s de tráfico a 60 fps y los jugadores no tienen retraso en su percepción, pero solo si el ping está por debajo de cierto umbral, porque la nueva posición de las bolas necesita ser transmitida.
Además, hacer trampa es fácil con este sistema y hay una alta posibilidad de perder la sincronización con una conexión con mucha pérdida, pero ¿a quién le importa hacer trampa en el pong?
fuente