Para o meu projeto atual, implementei um sistema baseado em componente / entidade , basicamente seguindo a maioria das melhores práticas existentes nessa área indefinida .
Então, eu tenho Entidades (um pouco estendidas) , que são basicamente um int
ID, um Nome legível por humanos, um std::map
dos componentes e um long
"indicador de tipo" que é usado para mostrar quais componentes estão presentes (eu tenho dois enum
para todos os componentes) tipos e sempre que um componente é adicionado à entidade, eu automaticamente altero esse tempo por meio de operações bit a bit, comparo esta resposta ).
Depois, há os componentes , também bastante simples: int
ID, enum
como tipo de componente, ponteiro de entidade pai e uma std::map
de todas as propriedades que esse componente possui.
Por fim, alguns sistemas / gerentes que lidam com o processamento lógico real. Eles primeiro verificam se a Entidade atualmente processada possui um long
"indicador de tipo" correspondente = todos os componentes necessários para esse sistema estão presentes. Em seguida, ele acessa algumas propriedades, se necessário, ou chama diretamente algumas funções no respectivo componente ou envia algumas mensagens (por meio de um despachante de mensagens).
Conclusão: até aqui, um sistema baseado em entidade / componente bastante orientado a eventos combinado com uma abordagem orientada a dados (comparar, componentes não possuem variáveis de dados codificadas), mas um mapa genérico, como (alguns) componentes / arquétipos de componentes serão lidos posteriormente a partir de arquivos com a opção de adicionar dados adicionais, que não fazem parte do código real do componente.
Agora, eu também gostaria de introduzir as Árvores de comportamento (baseadas no AiGameDev BTSK ) nesse projeto, mas não tenho certeza se e como elas devem ser vinculadas aos componentes já existentes ou como integrar esses projetos em geral.
Várias idéias / pontos / perguntas relacionadas vêm à mente:
Meus BTs serão lidos a partir de arquivos (novamente). No momento, tenho dificuldade em ver como, no entanto, seria melhor fazer a conexão entre um
BT Action
nessa árvore e a codificação real no meu aplicativo. Devo criar algum tipo de mapa entre os nomes das ações usadas nos arquivos BT e um ponteiro de função para a implementação lógica real? Qual é a abordagem usual para resolver isso?Suponho que terei que criar BTs para todos os meus
Entity
tipos diferentes (portanto, para cada combinação de componentes relevante para a lógica do jogo / IA, conforme indicado pelos vários "indicadores de tipo" longos mencionados anteriormente). Como resultado, não faz sentido colocar asBT Action
implementações nos componentes, pois provavelmente muitos componentes estarão envolvidos por ação, não é?Então, a
BT Action
lógica deveria estar em um / vários sistemas separados (para cujos métodos o mapa da idéia nº 1 aponta para)? O sistema verificaria, de acordo com meulong
"indicador de tipo", se oEntity
BT atualmente está marcado e que foi instruído a executar uma determinada ação (= método no sistema) está realmente autorizado a fazê-lo (= possui os componentes necessários). Mas, se não (porque, por exemplo, o criador da BT ignorou uma situação específica, onde um componente necessário pode não estar mais conectado à Entidade no tempo de execução), nada aconteceria.
Questões:
- Existem conceitos comprovados para esse tipo de integração?
- Qual é a sua opinião sobre os meus 3 pontos acima?
- Alguma outra coisa que vem à mente, também em relação ao meu design baseado em componentes / entidades em geral?
fonte
Respostas:
Esqueça os ponteiros de função e pense nos objetos. Cada nó na árvore de comportamento (BT a partir de agora) corresponderia idealmente a um objeto no seu código. Esses objetos terão uma interface padrão para permitir que você os organize como uma árvore e para atravessá-los. Um conjunto de ponteiros de função é bom para o comportamento, mas não captura a estrutura da sua árvore.
Eu esperaria que as entidades tivessem um único componente BehaviorTree que armazena os dados relevantes para o BT dessa entidade. A execução do BT é feita pelo componente BT ou pelo subsistema BT, dependendo de como você lida com os componentes em seu sistema. Como praticamente qualquer coisa usando componentes, eles terão que se referir a outros componentes para fazer o trabalho, mas esses outros componentes não precisarão saber nada sobre BTs.
As diferentes ações disponíveis seriam, no nível mais simples, codificadas nos vários objetos do nó BT. Eles devem ser capazes de fazer a entidade relevante agir manipulando os componentes conforme necessário, por exemplo. acessando o componente de movimento para mover.
fonte