Diseño basado en componentes / entidades + Árboles de comportamiento => ¿Cómo integrar?

9

Para mi proyecto actual, implementé un sistema basado en componentes / entidades , básicamente siguiendo la mayoría de las mejores prácticas que hay en esta área bastante indefinida .

Entonces obtuve Entidades (ligeramente extendidas) , que son básicamente una intID, un Nombre legible por humanos, un std::mapcomponente y un long"indicador de tipo" que se usa para mostrar qué componentes están presentes (tengo una potencia de dos enumpara todos los componentes tipos y cada vez que se agrega un componente a la Entidad, automáticamente modifico ese largo mediante operaciones bit a bit, comparo esta respuesta ).

Luego están los componentes , también bastante simples: intID, enumcomo tipo de componente, puntero de entidad principal y una std::mapde todas las propiedades que posee este componente.

Por último, algunos sistemas / gerentes que manejan el procesamiento lógico real. Primero verifican si la Entidad procesada actualmente tiene un long"indicador de tipo" coincidente = todos los componentes necesarios para ese sistema están presentes. Luego accede a algunas propiedades si es necesario y llama directamente a algunas funciones en el componente respectivo o envía algunos mensajes (a través de un despachador de mensajes).

En pocas palabras: hasta aquí, un sistema basado en componentes / entidades basado en eventos bastante estándar combinado con un enfoque basado en datos (comparar, los componentes no tienen variables de datos codificadas, sino un mapa genérico, como (algunos) componentes / los arquetipos de componentes se leerán más tarde de los archivos con la opción de agregar datos adicionales, que no forman parte del código de componente real.

Ahora me gustaría también introducir Behavior Trees (basado en AiGameDev BTSK ) en ese proyecto, pero no estoy seguro de si deberían vincularse a los componentes ya existentes o cómo integrar esos diseños en general y cómo.

Varias ideas relacionadas / puntos / preguntas vienen a la mente:

  1. Mis BT se leerán de los archivos (nuevamente). Actualmente tengo dificultades para ver cómo, sin embargo, haría la mejor conexión entre un BT Actionárbol y la codificación real en mi aplicación. ¿Debo construir algún tipo de mapa entre los nombres de acción utilizados en los archivos BT y un puntero de función a la implementación lógica real? ¿Cuál es el enfoque habitual para resolver eso?

  2. Supongo que tendré que crear BT para todos mis diferentes Entitytipos (por lo que para cada combinación de componentes de lógica de juego / IA relevante como lo indica mi "indicador de tipo" largo mencionado varias veces). Como resultado, no tiene sentido incluir las BT Actionimplementaciones en los componentes, ya que lo más probable es que intervengan muchos componentes por acción, ¿verdad?

  3. Entonces, ¿la BT Actionlógica debería estar en uno / múltiples sistemas separados (a cuyos métodos apunta el mapa de la idea # 1)? Luego, el sistema verificará, según mi long"indicador de tipo", si el EntityBT para el que se verifica actualmente y si se le dijo que ejecutara una determinada acción (= método en el sistema) realmente tiene permitido hacerlo (= tiene los componentes necesarios). Pero entonces, si no (porque, por ejemplo, el creador de BT pasó por alto una situación específica, donde un componente necesario podría no estar conectado a la Entidad en tiempo de ejecución), no pasaría nada.

Preguntas:

  • ¿Existen conceptos probados para ese tipo de integración?
  • ¿Cuál es su opinión sobre mis 3 puntos anteriores?
  • ¿Alguna otra cosa que se me ocurra, también con respecto a mi diseño basado en componentes / entidades en general?
Philip Allgaier
fuente
Punto 1: los árboles de comportamiento no son más que un DSL visual utilizado principalmente para crear el comportamiento de los personajes. Un componente BehaviorTree no debe hacer nada más ni menos que un componente Script. Punto 3: ¿Cuál es la razón para usar un mapa sobre campos regulares?
Eric
# 1: ¿Qué significa "DSL" en este contexto? # 3: Lo siento, pero no puedo seguirte en este caso. ¿Te importaría explicar por favor qué quieres decir?
Philip Allgaier
1
probablemente lenguaje específico del dominio, es decir. Una sintaxis personalizada para trabajar con un problema muy específico.
Patrick Hughes
Patrick tiene razón, aunque una semántica también es parte de ella y "muy" puede descartarse de esta definición. - Re 3: Mis disculpas, debería leer: "¿Cuál es la razón para usar un mapa sobre campos regulares en componentes ?"
Eric
Re 3: Quiero la capacidad de especificar dinámicamente propiedades adicionales más tarde fuera del código C ++ (palabra de moda: basada en datos). En aras de la simplicidad, (al menos por ahora) puse todas las propiedades en este marco genérico (usando mapas), incluso aquellas que están arregladas en el código y, por lo tanto, podrían ser campos reales de C ++. Podría tener que volver a visitarlo más adelante, si se convierte en un problema de rendimiento ...
Philip Allgaier

Respuestas:

2

Actualmente me cuesta ver cómo, sin embargo, haría la mejor conexión entre una Acción BT en ese árbol y la codificación real en mi aplicación. ¿Debo construir algún tipo de mapa entre los nombres de acción utilizados en los archivos BT y un puntero de función a la implementación lógica real? ¿Cuál es el enfoque habitual para resolver eso?

Olvídate de los punteros de función y piensa en los objetos. Cada nodo en el árbol de comportamiento (BT desde este punto en adelante) correspondería idealmente a un objeto en su código. Esos objetos tendrán una interfaz estándar que le permitirá organizarlos como un árbol y atravesarlos. Un conjunto de punteros de función está bien para el comportamiento, pero no captura la estructura de su árbol en absoluto.

Como resultado, no tiene sentido incluir las implementaciones de BT Action en los componentes, ya que lo más probable es que intervengan muchos componentes por acción, ¿verdad?

Esperaría que las entidades tengan un solo componente BehaviorTree que almacena los datos relevantes para el BT de esa entidad. La ejecución del BT la realiza el Componente BT o el Subsistema BT, dependiendo de cómo maneje los componentes en su sistema. Al igual que con casi cualquier cosa que use componentes, deberán referirse a otros componentes para hacer el trabajo, pero esos otros componentes no tendrán que saber nada sobre los BT.

Las diferentes acciones disponibles se codificarían, en el nivel más simple, en los diversos objetos del nodo BT. Deben poder hacer que la entidad relevante actúe manipulando los componentes según sea necesario, por ejemplo. accediendo al componente de movimiento para moverse.

Kylotan
fuente
Párrafo n. ° 1: Sí, el BT en sí será un objeto (como dije como la versión de AiGameDev). Estaba pensando en los functores para las acciones en sí, pero su párrafo # 2 cambió eso. Por alguna razón, este enfoque realmente simple nunca se me ocurrió (la entidad tiene su propia instancia de miembro BT). Probablemente debido a todo el componente nuevo, ya no pensaba de manera clara y simple, así que estaba buscando una forma de mezclar componentes con el material BT, pero eso no es realmente necesario.
Philip Allgaier el
Lo principal en lo que me perdí anteriormente fue cómo conectar la acción con la entidad. Ahora está claro: las acciones saben a qué entidad a través de su árbol que a cambio conoce la entidad a la que pertenece.
Philip Allgaier el
@Philip Allgaier Tengo curiosidad, ¿cómo terminaste creando el nodo BT? ¿Lo creaste como 1 nodo de comportamiento = 1 entidad (que sería una gran cantidad de entidades por 1 objeto de juego), o creaste un nodo como una clase normal (no relacionada con ECS), o usaste otros enfoques? ¡Gracias!
cppBeginner