Problema de agrupaciones de componentes de procesamiento - Subsistema de entidad

8

Descripción de la arquitectura

Estoy creando (diseñando) un sistema de entidad y me encontré con muchos problemas. Estoy tratando de mantenerlo orientado a los datos y lo más eficiente posible. Mis componentes son estructuras POD (matriz de bytes para ser precisos) asignados en grupos homogéneos. Cada grupo tiene un ComponentDescriptor: solo contiene el nombre del componente, los tipos de campo y los nombres de campo.

La entidad es solo un puntero a una matriz de componentes (donde la dirección actúa como una ID de entidad). EntityPrototype contiene el nombre de la entidad y la matriz de nombres de componentes. Finalmente Subsistema (Sistema o Procesador) que funciona en grupos de componentes.

Problema real

El problema es que algunos componentes dependen de otros (Modelo, Sprite, PhysicalBody, Animation depende del componente Transform), lo que genera muchos problemas a la hora de procesarlos.

For example, lets define some entities using [S]prite, [P]hysicalBody and [H]ealth:
Tank:   Transform, Sprite, PhysicalBody
BgTree: Transform, Sprite
House:  Transform, Sprite, Health

and create 4 Tanks, 5 BgTrees and 2 Houses and my pools will look like:

TTTTTTTTTTT // Transform pool
SSSSSSSSSSS // Sprite pool
PPPP        // PhysicalBody pool
HH          // Health component

No hay forma de procesarlos usando índices. Paso 3 días trabajando en ello y todavía no tengo ideas. En diseños anteriores, TransformComponent estaba vinculado a la entidad, pero no era una buena idea. ¿Me puede dar algunos consejos sobre cómo procesarlos? ¿O tal vez debería cambiar el diseño general? Tal vez debería crear grupos de entidades (grupos de grupos de componentes), pero supongo que será una pesadilla para los cachés de CPU.

Gracias

mani3xis
fuente
Multijugador? (Es relevante)
Jonathan Dickinson

Respuestas:

2

Descargo de responsabilidad: puramente fuera de mi conocimiento de clase de sistemas.

Originalmente pensé, ¿por qué no usar una función hash en la ID de entidad para su índice?

De esa manera obtendrías

T[A]nk:   Transform, Sprite, PhysicalBody
B[G]Tree: Transform, Sprite
H[O]use:  Transform, Sprite, Health

and create 4 Tanks, 5 BgTrees and 2 Houses and my pools will look like:

OGAGAGGOGGG // Entity pool (letters corresopnding to entity type)
TTTTTTTTTTT // Transform pool
SSSSSSSSSSS // Sprite pool
P P P  P    // PhysicalBody pool
H      H    // Health component

O, sin embargo, fueron las entidades las que se colocaron. Puede tener grupos para todos los componentes y para las entidades y utilizar el grupo de entidades como el "maestro", de modo que las colisiones se verifiquen con la matriz de entidades. Pero, por supuesto, tiene el problema de reciclar componentes y entidades.

Si el diseño de su juego lo permite, puede planificar con anticipación a dónde va cada tipo de entidad para que pueda obtener el embalaje más eficiente posible. Digamos que las entidades 0-20 están reservadas para tanques, las entidades 21-30 para casas y 31-60 para BGTrees. Es posible que no pueda generar eficientemente infinitos baddos, y de alguna manera derrota el dinamismo de los sistemas de componentes, pero resolvería el problema. No veo una manera de tener tu pastel y comerlo también.

Estaba pensando en formas de acelerar el pase de renderizado donde tiene una RenderingComponentque contiene todos los datos que necesita el sistema de renderizado para que pueda pasar por una serie de estas cosas, pero luego hay una sobrecarga de copiar datos. Además, cada vez que desreferencia un puntero, está pensando si todavía está en el caché.

Si quieres un juego súper rápido, diría que planifiques tu asignación. Si quieres una arquitectura de juego flexible, despliega las tablas hash y las ID de cadena. Cada vez que desee flexibilidad, necesita crear abstracción y, por lo tanto, incurrirá en gastos generales.

TL; DR;
Según lo que describió, crearía un nivel superior RenderComponentcon punteros Spritey Transformcomponentes y le daría las referencias necesarias cuando inicialice la entidad.

(Disculpas por cualquier divagación percibida, también he estado pensando en esto en mi sistema, así que esta fue una oportunidad para pensarlo)

michael.bartnett
fuente
No sé si los mapas hash son tan efectivos. Quiero tener una entidad de sistemas donde los subsistemas contengan funciones DOD como: void update(u32 n, PhysicalBodyComponents* bodys, Transform* transforms)Quiero trabajar en muchas entradas y dividir esta función en múltiples núcleos. ¿Es posible con hashmaps?
mani3xis
Los hashmaps son simplemente una forma de identificar relaciones entre entidades y componentes. Esto depende de cómo esté configurado tu juego, pero no veo una manera eficiente de garantizar que tu bodysy tu transformsmatriz se alineen. Esto es algo que no puede evitar sin agregar una capa de abstracción o planificar su asignación. Siento que no tengo la experiencia para hablar sobre escalar a múltiples núcleos. Tal vez encuentre una pregunta sobre enhebrar y escalar o escriba la suya.
michael.bartnett
El escalado es fácil cuando las funciones funcionan en matrices lineales: puedo configurar un rango para cada núcleo y simplemente ejecutarlo. Por eso estoy tratando de evitar los hashmaps. Intentaré rediseñar este sistema de entidades. Tengo que tener mucho cuidado con los errores de caché: PS2 tiene RAM muy limitada, etc. Por cierto: nada es imposible :)
mani3xis
Nada es imposible, pero no todo es factible;). Puede luchar por la simplicidad y la elegancia de la implementación, la velocidad de ejecución y el consumo de memoria: elija dos. Cuando encuentre su solución, publíquela como respuesta. Estoy seguro de que no soy el único a quien le gustaría verla.
michael.bartnett