Cómo manejar una gran cantidad de pastillas en un juego MMO


26

¿Cómo los manejan juegos como Minecraft, o realmente cualquier juego MMO que tenga pastillas?

Digamos que el terreno genera 3 gotas de "suciedad" cada vez que excavas dicho terreno. Digamos que cada elemento tiene una animación de rotación calculada en cada cuadro. Si el número de recolecciones en el mundo es muy alto, eso sería una sobrecarga masiva inútil en el cómputo de trama para un cliente en un servidor dado, ya que es probable que muchos de esos artículos de recolección estén a años luz de usted.

Entonces, lo que pensé es que tienes que "hacer cosas" solo con las pastillas cerca del jugador local, pero aún así esto implicaría que cada cuadro que tengo que verificar si algún otro elemento de la pastilla está lo suficientemente cerca como para comenzar a animar.

Mi pregunta real es: ¿cómo han resuelto este problema otros MMO?


99
Además, en el contexto de Minecraft, después de que un cierto número de elementos estén lo suficientemente cerca entre sí (más de 3 del mismo elemento en el mismo espacio de bloques), el servidor reemplaza las 3 instancias con una instancia agrupada que contiene el tipo de bloque ( minecraft:dirt) y un conteo (30), de modo que cuando el jugador está lo suficientemente cerca como para recogerlo, solo agrega la mayor cantidad de conteo posible al inventario del jugador. Si el jugador solo tiene espacio para 6 artículos y una pila de 30 está en el suelo, el jugador recogerá los 6 y la pila en la cuenta del suelo se reduce a 24.
Zymus

66
@Zymus Vale la pena señalar que en realidad disminuyó el rendimiento de la garrapata para un número moderado de elementos caídos porque todos están constantemente buscando los cercanos.
user253751

Respuestas:


48

Simplemente cargando esas partes del mundo en la memoria que están cerca del jugador. Cualquier otra cosa está suspendida en el disco duro. Cuando hay un pequeño objeto a unos dos kilómetros de distancia, el jugador no puede verlo y no puede interactuar con él. Por lo tanto, no hay razón para actualizarlo o enviarlo a la GPU para su representación. Cuanto más pequeño es el objeto y su rango de interacción, menor es el rango alrededor del jugador donde necesita cargarlo.

En cuanto a descubrir qué hay cerca del jugador: eso se reduce principalmente a almacenar el mundo en una estructura de datos optimizada para la búsqueda espacial. Los buenos candidatos para eso son el hashing espacial y los árboles multidimensionales .


Gracias por la rápida respuesta. Estaba pensando en usar Unity porque supongo que usa algún tipo de partición espacial para verificar los colisionadores de gatillo, por lo que crearía un colisionador de círculo grande alrededor de mi personaje y cada elemento dentro de él estaría "animado". ¿Es esta una forma de implementar su respuesta? ¡Corrígeme si me equivoco, saludos!
Alakanu

2
@Alakanu Se puede usar si desea que los objetos sean visibles a largas distancias, pero solo realice ciertos comportamientos intensivos de cómputo cuando esté cerca del jugador (y simplemente girar algo alrededor de su eje y no debería ser muy costoso). Pero el desafío real al implementar un juego de mundo abierto en Unity es crear instancias de forma inteligente y destruir objetos del juego mientras el jugador se mueve por el mundo (o incluso mejor: use la agrupación de objetos en lugar de crear instancias y destruir).
Philipp

Sí, la agrupación de objetos es obligatoria en esta situación :) Ok, ¡muchas gracias!
Alakanu

3
@Alakanu Puedes consultar el concepto de "Trozos cargados" de Minecraft para obtener más información sobre cómo se aplica esta respuesta a ese juego.
T. Sar - Restablece a Mónica el

1
Esto no solo es cierto para las pastillas. CUALQUIER objeto que esté demasiado lejos del jugador puede ser tratado de esa manera. A veces, incluso los objetos que están cerca del jugador. Imagine una casa con un interior completo pero no hay necesidad de renderizar hasta que realmente ingrese a la casa.
Zibelas

22

Tienes dos cosas muy diferentes para administrar:

  1. El servidor debe administrar todo el mundo, de manera autoritaria. Para eso, es necesaria la comunicación con N clientes (donde N es "masivo").

  2. El cliente podría , en principio, saber sobre el mundo entero, pero no es necesario . Para el cliente, es suficiente saber qué hay cerca del jugador. Suponiendo, por ejemplo, una partición bastante gruesa en forma de cuadrícula, necesitaría conocer solo la celda del jugador y las 26 celdas alrededor del jugador (u 8 celdas en caso de que tenga una cuadrícula 2D). Una cuadrícula algo más fina es mejor, pero entiendes la idea.

Ahora, muchas pastillas, ¿qué es "mucho"? Cavas quizás 5 cosas por segundo, eso es quizás dos docenas de números que deben actualizarse en el servidor, y el servidor puede tener que transmitirlos a algún otro jugador cuya área de interés se superponga a tu celular. Para una computadora, esta es una cantidad de datos bastante ridícula, y una cantidad de cálculo despreciable. Puede convertirse en un desafío cuando hay cientos / miles de jugadores en la misma celda (entonces su partición es demasiado tosca).

El servidor no necesita saber, ni preocuparse por la rotación de las pastillas o dichos detalles. ¿Por qué lo haría?

Al cliente tampoco le importa, ya que esto es solo un dulce visual que el cliente puede inventar sobre la marcha.

Lo que es necesario desde el punto de vista del servidor es saber que estaba cavando en (30, 40, 50) en el nodo en el que se encuentra, y decide que esto genera, por ejemplo, tres objetos de tipo 5 o un objeto de tipo 7 con un recuento de 3. Eso es todo lo que le importa, y es todo lo que te dice. También incluirá esa información en los datos enviados a alguien que mueva su área de interés a través de la celda de la cuadrícula más tarde (suponiendo que todavía esté allí para entonces).

Al cliente le dicen tres objetos engendrados allí, bla, bla. Ahora, ya sea que el cliente muestre un mapa de arte ASCII donde ahora hay una 'D' o si muestra un montón de tierra en rotación, es lo mismo. Si las pilas tienen diferentes rotaciones o si solo las que están cerca de tu jugador rotan, son todas iguales. Es solo algo que se muestra en su monitor, no afecta a nadie más.

Por lo tanto, en el caso concreto en el que desea rotar solo montones de tierra cercanos, puede hacer una verificación de rango de todos los objetos que conoce. Como el conjunto de datos no es grande, incluso la fuerza bruta sobre todo funcionará.

Puede (y debería), dependiendo del tamaño de su partición, podar trivialmente las celdas de la cuadrícula que están demasiado lejos.

Por supuesto, puede subdividir aún más su celda y usar algo súper inteligente. Usa un árbol kd si lo deseas, pero no esperes grandes ganancias. Puede podar cosas con distancia de Manhattan, o puede ordenar sus cosas en una pequeña cuadrícula propia ... pero ¿por qué?

Una verificación de distancia (distancia realmente cuadrada, pero es lo mismo para usted) son solo dos multiplicaciones y una suma (optimizada para MUL, MADD, por lo que en realidad solo son dos operaciones), seguidas de una rama o movimiento condicional. Eso es casi tan rápido como cualquier otra operación que no pode celdas de cuadrícula completas a la vez. De hecho, esto es algo que incluso podrías hacer en la GPU ...

Al ver cómo tendrá unos pocos cientos, o como máximo algunos miles de comprobaciones de distancia en la misma posición (la distancia al cuadrado funciona bien), realmente no tiene muchos problemas solo para hacer ese cálculo, incluso más, ya que es más bien un caché. iteración amigable sobre memoria contigua, y con movimientos condicionales, es muy barato. Algo como (pseudocódigo) rot = r[i] + 1; r[i] = ((dx*dx+dy*dy) < DIST_SQ) ? rot : r[i];. Esa es una iteración sobre una matriz de unos cientos de valores por cuadro. A la computadora no podría importarle menos hacer eso, son cargas y tiendas contiguas, ALU simple, sin ramas, y solo unos pocos miles de iteraciones.

Esto (muchos a uno) no es la misma clase de problema (muchos a muchos) que en el servidor. Realmente, el cliente no es el problema.


Lo siento, pensé que estaba claro que estaba hablando de un cliente cuando comencé a hablar de framerate.
Alakanu

1
Pero el cliente nunca es el problema. El cliente es muy no masivo y muy local, necesita saber mucho menos que el servidor. Idealmente, el cliente conoce el nodo de partición espacial (sea lo que sea, digamos, la cuadrícula) en el que se encuentra el jugador y los que lo rodean inmediatamente, y eso es todo. Las actualizaciones son, por lo tanto, muy modestas a menos que mil jugadores estén uno al lado del otro. Normalmente, solo necesita deltas para uno o dos objetos, y el contenido de un nuevo nodo de cuadrícula después de moverse hacia una dirección durante más de la mitad del ancho de un nodo. Todo lo demás: no es tu problema.
Damon

1
El punto es que ser demasiado inteligente puede ser una idea enormemente estúpida. Su mundo ya está necesariamente dividido espacialmente, con un número manejable de objetos en cada nodo. Las CPU modernas (y las GPU aún más) son buenas para procesar secuencialmente grandes cantidades de datos de SoA. No les gusta la ramificación incoherente, y les gusta aún menos el acceso incoherente a la memoria, que sin embargo es exactamente lo que hace "solo el proceso cercano". Para números manejables (unos cientos, algunos miles), "procesar todo" dentro de una celda es perfectamente adecuado, y probablemente lo mejor que puede hacer.
Damon

1
@Alakanu Esto me parece una respuesta detallada y completa a su pregunta. Si crees que no es una respuesta, o la has entendido mal o tu pregunta no es tan clara que Damon, yo y todas las personas que votaron por esta respuesta la han entendido mal.
David Richerby

2
@Alakanu Realmente pasas una gran cantidad de tiempo quejándote de las personas que intentan ayudarte. Buena suerte con eso.
David Richerby

2

@ T.Sar escribe en un comentario que debe consultar el concepto de "trozo cargado" de Minecrafts para obtener más información. Si lo haces, ten en cuenta que esto es bastante complicado en Minecraft debido a que las personas construyen máquinas en el juego.

Sigue una versión muy simplificada:

El mundo está dividido en regiones cuadradas (trozos). En Minecraft también hay una división de altura, pero la mayoría de los mmos no necesitan eso.

El cliente del juego solo se preocupa por las regiones cercanas al jugador. Esto es mucho más simple que dibujar un círculo alrededor del jugador, pero es lo suficientemente bueno.

En Minecraft, las regiones son bloques de 16x16, y el cliente sabe acerca de las regiones de 9x9, 4 regiones en cada dirección. (4 regiones este + región jugador está en + 4 regiones oeste = 9 regiones en total. Mismo norte / sur)

No hay nada mágico en estos números, usa lo que tenga sentido en tu juego.

El cliente solo anima cosas dentro de esta área. El servidor solo calcula cosas como monstruos errantes en regiones cercanas a algún jugador.

Cuando un jugador camina dentro de una región, no sucede nada especial, cuando cruza el borde de una región, el "borde de la animación" se empuja una región. El cliente debe preguntarle al servidor sobre las regiones que ahora ve.

No hay nada de malo en tener varios límites de animación anidados. Por ejemplo, un objeto animado cae en un área de 3x3, monstruos errantes en un área de 5x5 y solo muestra el paisaje en un área de 9x9.

El servidor mantiene una "versión congelada" de regiones que ningún jugador ve. Si esto requiere mucha memoria, es posible que desee descargarlos después de un tiempo. La próxima vez que llega un jugador, la región se vuelve a cargar sin que el objeto caiga. Necesitas ser más rápido la próxima vez, Jugador 1.


La distancia de extracción es ajustable, pero en este caso 8 fragmentos son 9x9 y es una decisión del lado del cliente, aunque puede informar al servidor para acelerar las cosas (para que el servidor no envíe datos que el cliente no procesará). Además ... ¿Doom y Quake no resolvieron el problema de representar solo lo que tiene sentido?
SparK

Sobre la desaparición de los objetos caídos ... en Minecraft, el objeto solo "envejece" cuando hay un jugador cerca. Por lo tanto, puede "guardar" un elemento caído en un fragmento descargado y obtenerlo más tarde.
SparK
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.