Estoy implementando MMO donde el jugador vuela en el espacio en su nave estelar controlando con teclas de flecha y cooperando con otros jugadores.
Quiero implementarlo para que el jugador pueda esquivar su nave del cohete o algo más, así que estoy tratando de predecir el estado del juego completo en el lado del cliente usando el mismo algoritmo de simulación mundial que el uso del servidor. Ese mundo del juego está escrito en C # y se llamará directamente dentro del cliente (está escrito en Unity3D) y a través de CLR en el servidor C ++ (en Linux). Conexión a través de UDP.
El problema es cómo mantener, por ejemplo, 1000 jugadores en un solo mapa (excluyendo todos los demás objetos del juego, mobs ...): Digamos que lo haré:
- sincronizar servidor con clientes 50 veces por segundo
- enviar a cada cliente estados de los objetos del juego (y los jugadores) que puede ver (dentro de cierto radio)
- tiene que enviar 100 objetos a cada jugador dentro de su radio de visión
- debe enviar un promedio de 50 bytes por objeto de juego (es id, x, y coords, rotación, estado ...)
por lo tanto, deberá tener dicho ancho de banda de red: 1000 (clientes) * 50 (veces por segundo) * 100 (objetos para enviar a cada jugador) * 50 (bytes por objeto) = 250 000 000 bytes por segundo. ¡Es imposible!
¿Es posible reducir este valor de alguna manera? Por ejemplo, permita que los clientes simulen completamente sus mundos de juego (durante un largo período de tiempo) y envíenles solo entradas de otros clientes y sincronicen mundos de juego, digamos, cada varios segundos, pero causará problemas de desincronización extraños debido a cálculos de flotación. .
De todos modos, ¿cómo se programan estos juegos de manera común? Gracias.
fuente
Respuestas:
Solo necesita unas 30 actualizaciones (o incluso menos, tal vez 10 o 20) por segundo. interpolar las posiciones de los objetos en movimiento del lado del cliente. En general, solo debe enviar datos cuando sea REALMENTE necesario. En WoW puede recibir más actualizaciones de los jugadores con los que está en un grupo que de los jugadores que están en la misma ubicación. Además, si otro jugador está lejos de ti, no recibes tantas actualizaciones por segundo sobre él.
Luego, solo envíe una instantánea completa a cada jugador cuando se conecte. Después de eso solo envía los cambios de los objetos del juego. Si no se produjo ningún cambio, no lo envíe.
Luego, ¡haga un uso intensivo de BitVectors o de cómo los llame para reducir la cantidad de datos innecesarios! Ejemplo: También puede intentar escribir un flotante usando solo un byte (en un rango de 0 a 1 o -1 a 1) para que solo tenga 256 o 128 valores diferentes. Pero el jugador no notará ningún movimiento brusco gracias a las interpolaciones.
Mira esto para ver un ejemplo con LidgrenLibrary sobre cómo comprimir datos: http://code.google.com/p/lidgren-network-gen3/wiki/Optimization
A continuación: intente reducir el radio de visión de los jugadores mientras se mueven, y solo transmita información importante en ese momento. Luego, cuando dejen de aumentar su radio de visión nuevamente. Puede usar un sistema de hashing espacial o un árbol bsp para reducir la sobrecarga de buscar objetos que están "dentro del rango". Esta es una buena lectura para el tema: http://en.wikipedia.org/wiki/Collision_detection
Comprima también los datos USTED MISMO, solo USTED conoce la estructura de datos y la coherencia temporal en los datos (que pueden y deben explotarse). Debe usarse un algoritmo general como Bzip2, Deflate, lo que sea, ¡pero solo como la etapa final de compresión!
Además, para obtener información que no sea crítica para el juego, también puede emplear técnicas P2P adicionales. Ejemplo: un jugador reproduce la animación "hola" (solo un efecto gráfico). El jugador envía esta información al servidor, pero el servidor no transmite la información a los otros jugadores. En cambio, este efecto no crítico es enviado por el propio jugador a los otros clientes dentro del alcance.
EDITAR (por el comentario):
Métodos adicionales para disminuir el conteo de bits promedio por segundo para cada jugador:
Usted escribió que envía "El objeto no cambió". No hay razón para hacer esto. Si le preocupa la pérdida de paquetes (y la sincronización de su simulación debido a esto) considere lo siguiente: En cada paso fijo (por ejemplo, 100, 200, 300, 400 ...), controle el estado de la simulación y envíelo al servidor . el servidor confirma o envía una instantánea completa de todos los datos.
Para cosas como cohetes o incluso jugadores, puede emplear no solo interpolación sino también extrapolación para hacer que la simulación sea más realista. Ejemplo 'Cohete': en lugar de actualizar con mensajes como "Ahora está en la posición x", simplemente envíe un mensaje que contenga lo siguiente: "Cohete generado: posición (vector), Tiempo (en el paso de simulación que se generó el cohete), velocidad ( vector)". Por lo tanto, ni siquiera tiene que incluir la rotación porque la punta siempre estará en la dirección de "velocidad".
Combine múltiples comandos en un mensaje y nunca envíe mensajes de menos de 16-20 bytes porque el encabezado udp será más grande que el mensaje en sí. Tampoco envíe paquetes más grandes que la MTU de su protocolo porque la fragmentación reducirá la velocidad de la transmisión.
fuente
Aquí hay dos enfoques:
Primero:
cambie a física determinista, envíe comandos de jugador, acciones ai, objetos a la vista y lo que no pueda determinarse del lado del cliente a los clientes. Esto debe incluir no comandos, una confirmación de que hasta cierto punto en el tiempo solo se aplican los comandos que se han enviado y recibido.
El cliente debe ejecutar dos o tres simulaciones simultáneas.
1: se detiene cuando faltan datos para el siguiente paso.
2: Continúe usando datos de conjetura y proporcione el estado utilizado para la representación. 3: Cada vez que el 1 no se detiene, esta simulación copia el estado del no 1, se pone al día con la hora actual y toma el control del no 2, que luego se descarta.
Si la actualización es lo suficientemente rápida, puede omitir la diferencia entre no 2 y no 3 y simplemente descartar los datos antiguos de inmediato.
Segundo:
no use física determinista, haga lo mismo que antes, pero envíe "fotogramas completos" una vez cada pocos segundos. Puede omitir fácilmente la transferencia de cosas temporales como balas.
En ambos casos, es posible que desee tener cuidado con el cliente que predice que alguien morirá, es un poco tonto ver a un oponente sin explotar.
Y +1 por hacer los cálculos, demasiadas personas no logran hacer estimaciones simples de uso de recursos.
fuente
Pocas preguntas primero.
¿Son los 'cohetes u otra cosa' inteligentes o tontos? Si son tontos, todo lo que necesita es la marca de tiempo del fuego, el origen y el vector para simular su camino. Si son inteligentes, ¿qué tan inteligentes son? ¿Puedes calcular en el momento del incendio que van a acertar o fallar? Si es así, puede simular la ruta completa en el cliente. ("En T13 el misil golpeará la nave porque la jugada perdió la tirada de esquivar / el tirador obtuvo un golpe crítico").
En general, aunque no hay prácticamente ninguna razón para: A) tener una frecuencia de reloj de 50Hz, (la mayoría de los tiradores se escapan con 15-20 y los MMO menos que eso). B) enviar el estado completo en cada cuadro. (¿Importa la rotación de un misil en el espacio? ¿O puede suponer que su 'frente' está orientado a lo largo del vector en el que viaja?)
Dedique tiempo a la predicción y la interpolación, y verá que su ancho de banda se desploma. Un proyecto en el que trabajé tenía una tasa de actualización de 10Hz, y una representación de estado de objeto de creo 14 bytes. (¡Comprima todo lo que pueda! Creo que usamos 6 bits para definir la rotación alrededor del plano xy luego otros 6 bits para una inclinación por encima / debajo de ese plano, parecía indistinguible de enviar una matriz rotacional / cuaternión real).
Otra cosa que puedes hacer es priorizar objetos. Mostrar, tal vez hay 100 objetos en el conjunto relevante, pero ¿conoces su punto de vista en el servidor? Si algo no está en su opinión, ¿puede eliminar su frecuencia de actualización en un orden de magnitud?
La idea general no es hacer una simulación perfecta en el cliente, eso es imposible, la idea es hacer un juego divertido donde los jugadores no se den cuenta de que no es una simulación perfecta.
fuente