Para empezar, tengo una buena cantidad de experiencia en redes (hardware, enrutadores, ej.) Pero muy poco conocimiento más allá de los conceptos básicos de la programación de redes. Esto puede parecer una pregunta estúpida, pero quiero saber en qué me estoy metiendo mientras entiendo la implementación del modo multijugador en mi juego.
Estoy creando un mundo basado en mosaicos, que se genera a través de una simple matriz 2D. Digamos algo como Mundo [100] [100], por simplicidad.
Actualmente, el método de renderizado solo renderiza los mosaicos en función de la resolución de la ventana, más un mosaico (para un procesamiento uniforme durante el movimiento). No importa cuán grande sea el mundo, (10x10, 1 millón x 1 millón) el rendimiento es perfecto.
La jugabilidad no necesita más que saber qué hay actualmente visible (representado en la pantalla +1) y, como máximo, ALGUNA información de fichas en un área alrededor del jugador.
Entonces, cualquier cosa más enviada por el servidor no sería la información completa del mosaico. Ex. Los elementos que se encuentran en el suelo, tipo de suelo, árboles, etc. no serían importantes en el área fuera de la vista del jugador, pero solo serían lo que el Cliente / Jugador necesita saber en esas fichas. (Por ejemplo, los 'nombres entrantes' de Ultima Online donde los jugadores podían saber que un Personaje [jugador o monstruo] estaba más allá de las fichas en su vista renderizada).
No sé mucho acerca de las redes, por lo que tal vez al aprender esto pueda responder a mi pregunta. Sin embargo, tengo curiosidad si esta es una solución factible o si la idea es simplemente ridícula.
La información que se envía sería sobre un área de mosaicos de 10x15, y cada mosaico contiene información sobre lo que está en el mosaico. Más eficientemente, todo sería un Objeto, donde el mosaico contiene todos los Objetos en el mosaico. Ex. La ficha [4] [4] contiene la Espada # 23452, Rock2, Tree5, Player3, Monster4.
Las baldosas vacías enviarían nada más que el tipo de terreno [Hierba, Arena, Agua] si aún no se han cargado durante la Inicialización / Carga. Algunas fichas tendrían un puñado de objetos [Tree2, Sword # 924, Gold, Corpse, Rock3].
Por lo tanto, no puedo imaginar que un mosaico tenga mucha información para enviar al Cliente desde el Servidor, ya que el Cliente solo necesita saber la Textura que necesita cargarse y la Posición para colocarla en la pantalla. La posición es solo dos enteros y Texture es un número entero para una lista de archivos para decirle al cliente que renderice.
En el momento más loco, el Servidor tendría que enviar 150 mosaicos con información de solo un puñado de Objetos OnLOAD, y a partir de ese momento, la actualización solo cambiará a mosaicos (si los hay) y cualquier mosaico nuevo (10 a 15 cada vez que un jugador se mueva en una dirección ) y la dirección del movimiento de los personajes en pantalla (para que el cliente pueda simular un movimiento suave entre los mosaicos).
Supongo que estoy en lo cierto al pensar que se trata de una cantidad increíblemente baja de información que se envía a través de Internet o entre pares, por lo que debería tener pequeños problemas con el rendimiento incluso con conexiones lentas. ¿O soy tan ignorante de las redes que mi mente se sorprenderá cuando finalmente pueda abrir mi libro sobre redes multijugador?
Si se está enviando una cantidad muy baja de información entre Cliente / Servidor, ¿tendría más sentido simplemente cargar todo el Mundo en la inicialización? O 'Mapa' si el mundo es excesivamente grande. Y luego, después de CARGAR, ¿envía solo los mosaicos que se actualizan?
Todavía estoy pensando cómo debo tratar específicamente con los datos. El libro que estoy usando como referencia quiere que tenga una lista vinculada, donde agrego y elimino objetos, por lo que todo es un bool. "¿Hay un personaje? ¿Hay un árbol?"
Estaba pensando en un enfoque diferente, como un contenedor que contiene objetos, y la lógica del Servidor que envía solo lo que se requiere para decirle al Cliente qué renderizar. Posiblemente con objetos que contienen información de red dentro de sí mismo, que se envía cuando el servidor lo solicita.
Respuestas:
Estás en el camino correcto.
Considera Minecraft. Minecraft solo carga las áreas (también llamadas fragmentos) que rodean inmediatamente a los jugadores. Así es como el servidor puede ejecutarse sin quedarse sin memoria, y por qué los clientes no se estancan del tráfico de red.
Esto es exactamente lo que debes hacer. Solo envíe los datos que necesita enviar.
Si solo está enviando una matriz 2D de IDS de mosaico, el tamaño de los datos puede ser muy bajo, especialmente si tiene menos de 256 tipos de mosaico diferentes. En ese caso, puede usar un solo byte (o un carácter sin signo). Entonces, si está enviando fichas de 100x100 al jugador, y cada ficha solo consta de un solo byte ... Usted entiende la idea. No es mucha información.
La comunidad de Minecraft ha hecho un trabajo maravilloso documentando su protocolo: http://mc.kev009.com/Protocol
http://www.minecraftwiki.net/wiki/Classic_server_protocol
fuente
En general, es una buena idea enviar solo la información al cliente que se supone que debe mostrarse al jugador. Seguir este principio reduce el tráfico de red y evita las trampas.
Pero tenga en cuenta que cuando el jugador mueve a su personaje, ciertamente desea comenzar el movimiento en el lado del cliente antes de recibir la confirmación del servidor para que el juego parezca menos lento y más receptivo. Eso probablemente significará que también desea comenzar a desplazar la pantalla a un área que aún no está cargada. Esto te obliga a dejar esta parte del mapa en blanco y reemplazarla con el mundo real cuando se haya cargado. Eso sería un gran interruptor de inmersión. Por esa razón, debes precargar el área en un cierto radio alrededor de la pantalla del jugador.
El tamaño del área precargada depende de qué tan rápido puedan moverse sus jugadores y cuánto tiempo será su latencia promedio.
fuente
La cantidad de datos que envía desde el Servidor al Cliente puede ser INCREÍBLEMENTE insignificante. Si esto es todo lo que necesita enviar, sugeriría vehementemente cargar todo lo que pueda en Load, por lo que se requieren aún menos datos. La cantidad enviada en carga será lo suficientemente pequeña como para justificar el tiempo de carga, el uso de la memoria será casi inexistente a menos que su mundo esté ridículamente sobredimensionado, y necesitará actualizar casi ningún dato.
Me imagino que también podría hacer algunos trucos para optimizar la predicción de retraso que compensa el retraso promedio que experimenta un usuario, lo que permite un movimiento predecible con los personajes.
Además, priorizar los datos insignificantes con el movimiento del personaje y las acciones / reacciones del personaje con la mayor prioridad puede ayudar a garantizar que incluso los jugadores retrasados sientan muy poco retraso.
fuente