Existem várias maneiras de representar e implementar sistemas de componentes de entidades, mas aqui está uma explicação de uma maneira. Lembre-se de que não há uma definição concreta de arquiteturas de entidade / componente / sistema, portanto, essa é apenas uma implementação.
Vou apresentar uma analogia para arquiteturas de entidade / componente / sistema que podem ajudar. Vamos pensar em uma entidade como uma chave.
A entidade
As chaves também têm dentes (azul escuro). Os dentes da nossa chave de entidade são os componentes que a compõem. Você pode distinguir as entidades por seu ID, mesmo que elas tenham os mesmos dentes. Então, no que as chaves se encaixam? Fechaduras. Fechaduras são nossos sistemas. Por exemplo, um sistema de movimento.
O sistema
A fechadura só funciona se nossa chave tiver dentes para posição e velocidade. Este sistema processa apenas entidades que possuem uma posição e uma velocidade. Existem várias maneiras de configurar como esses sistemas reconhecem quais entidades processar, mas uma maneira é usar a long
. Cada bit é reservado para um tipo de componente. No nosso exemplo, vamos assumir um tipo de 4 bits em vez de um comprimento de 64 bits. Nossa entidade de exemplo teria todos os componentes disponíveis. Então é a chave seria 1111
. Em seguida, o sistema está procurando por qualquer entidade que possua um 11--
. (O -
representante não se importa, porque o movimento não se importa se houver um sprite ou saúde). Pode verificar uma entidade com uma AND
operação simples . Portanto, nossa entidade corresponde se ((1111 & 1100) == 1100)
. Se eu te perdi lá, confira um pouco mais sobre as operações bit a bit .
Como você pode ver, os sistemas têm acesso a recursos externos. Eles podem acessar a hora, gráficos, som e assim por diante. Eles são simplesmente pequenos processadores que pegam uma chave de cada vez e processam dados. Você vê que o sistema de movimento leva a velocidade, tempo delta e posição; depois faz alguns cálculos e armazena o resultado novamente na posição.
As chaves de entidade são realmente fáceis de gerar. Você pode adicioná-los ou removê-los à vontade. A entidade não se importa, é apenas uma maneira de agrupar e reter os componentes. Os componentes não têm interdependência. Quanto mais os componentes se aproximam da interação entre si, é quando um sistema opera neles e usa dados de um para atualizar outro, como nosso exemplo de movimento.
Vamos dar uma olhada em outro sistema para ajudar a solidificar a ideia:
Este é o nosso sistema de desenho. Ele procura por componentes que correspondam 1-1-
. Essa entidade corresponde porque: ((1111 & 1010) == 1010)
Além disso, você pode ver que esse sistema envia informações para a tela, desenhando o sprite de entidade em sua posição.
OK, mais um. Vamos olhar para outra entidade e ver como ela pode se encaixar no nosso exemplo até agora.
Como você pode ver, essa entidade possui menos componentes anexados a ela. Observando os componentes que possui, parece que ele pode ser um item estático como uma rocha. Apenas tem uma posição e um sprite. Não vai se mexer e não será afetado por nenhuma mudança de saúde. Essa entidade produziria uma chave 1010. Então, quais sistemas operam nessa entidade? Vamos checar:
Contra o nosso sistema de movimento:
((1010 & 1100) != 1100)
Não. Parece que o sistema de movimento não se importa com essa entidade, porque não possui os componentes necessários.
Contra o nosso sistema de desenho:
((1010 & 1010) == 1010)
Ei, isso é uma partida. Essa entidade será operada pelo sistema de desenho. O sistema de desenho desenhará o sprite na posição definida.
Espero que você possa ver como seria fácil adicionar outro sistema que usaria nossos componentes e operasse neles. Deixe-me garantir que resolvi suas perguntas:
E se vários sistemas precisarem acessar o mesmo componente? Onde os dados devem ficar?
Normalmente, os sistemas operam um após o outro. Eles processam todas as entidades que atendem aos requisitos e, em seguida, o próximo sistema faz o mesmo e assim por diante. Os dados vivem com a entidade. Não deve haver nada armazenado no sistema, é apenas um bloqueio que é ativado, a chave é onde as informações ficam e se movem de bloqueio em bloqueio.
Como são construídas as entidades? Os sistemas estão intrinsecamente vinculados a um componente? Se eu quiser introduzir algum novo componente, também tenho que introduzir um novo sistema ou modificar um existente?
Entidades são apenas sacos de componentes. Eles têm um ID exclusivo e uma lista de componentes. Os sistemas são vinculados apenas aos componentes da maneira descrita acima. Você pode ter componentes sem sistemas que os operem, mas isso é inútil. Da mesma forma, você pode ter sistemas que estão procurando componentes que nenhuma entidade possui. Isso é menos inútil, porque eles podem estar apenas esperando a criação de uma entidade que corresponda ao seu bloqueio. Então, sim, se você introduzir um novo componente, você deseja criar um sistema que utilize esse componente. Caso contrário, você está apenas adicionando dentes à sua chave para uma trava que não existe.
Se minha entidade é apenas um ID, como posso saber que a entidade do meu robô precisa ser movida ou renderizada e, portanto, modificada por algum sistema?
Acho que respondo a isso com a ideia de uma long
chave que define os componentes contidos em uma entidade. Você sabe porque a chave se encaixa na fechadura.
Ufa! Esse foi um longo post! (Ou pelo menos parece isso no meu monitor grande.)