Como lidar adequadamente com a colisão em um jogo baseado em componentes?


11

Tentando entender as maneiras de lidar adequadamente com a colisão em um jogo projetado em torno de componentes.

Vejo que muitos exemplos são PhysicsComponentadicionados à lista de componentes da entidade, mas a implementação real está me confundindo.

Para que isso funcione, PhysicsComponentseria necessário acessar o mundo ao seu redor. Isso não faz sentido para mim. Um componente não deveria desconhecer não apenas seu contêiner (a entidade), mas também o contêiner de seu contêiner (o mundo)?

Para mim, parece que o nível ou a cena deve manter uma lista dessas entidades e a cada atualização do jogo, percorrer as entidades para determinar qual colisão.

Minha pergunta é em primeiro lugar, se isso é bom ou não, e em segundo lugar, como determinar quais entidades podem colidir. Suponho que entidades sólidas possam implementar uma interface IRigidBody vazia, para que o nível possa determinar quais entidades na lista suportam colisão. Mas isso está quebrando o design do componente?

Em vez disso, eles devem conter um componente RigidBody vazio? Na verdade, isso pode ser melhor porque nem sempre está vazio e essa abordagem é mais à prova de futuro. O único problema com isso é a complexidade. A cena teria que percorrer não apenas todas as entidades, mas também os componentes de todas as entidades para determinar se ele tinha esse componente RigidBody.

Em terceiro lugar, quando colidem, ambas as entidades devem ser informadas de alguma forma e também não tenho certeza de como fazer isso.

Digamos que ambas as entidades contivessem um HealthComponent e, quando colidissem, sua saúde seria diminuída por algum valor arbitrário, 5. Suponho que seria responsabilidade da cena lidar com isso quando detectar uma colisão entre duas entidades?

Mas então a cena é responsável por demais? Eu pude ver isso possivelmente ficando fora de controle e se tornando pesado quando a cena é responsável por muitas coisas que as entidades não deveriam (?) Ter acesso.

Editar: pergunta atualizada com mais detalhes.


4
Esta resposta parece apropriada para o link para: gamedev.stackexchange.com/questions/13797/…
Andrew Russell

A resposta vinculada de Andrew, a resposta de James e a resposta de Nick Wiggill merecem + 1s. Pense nos componentes mais como dados do que como uma classe típica com dados e métodos (não que eles não tenham métodos, mas eles não devem ter muita responsabilidade). Veja o sistema de componentes Artemis ( piemaster.net/2011/07/entity-component-artemis ) para obter um exemplo de uma boa estrutura de componentes.
michael.bartnett

Respostas:


5

Honestamente, do ponto de vista do design de componentes, meus componentes não se conhecem a menos que precisem (e isso é muito raro). Mesmo assim, eu geralmente prefiro que os componentes conversem com algum sistema de gerenciamento dos referidos componentes, em vez dos componentes diretamente. (A interface de script se parece com seu objeto a objeto, mas não está no mecanismo real, hehe).

Para esse fim, eu ficaria do lado do que você disse primeiro e seguiria com os componentes físicos que existem onde quer que os objetos precisem ser testados quanto à sua colisão. Agora, claramente, esses objetos podem precisar informar outros componentes sobre si mesmos após a resolução de uma colisão, mas, como mencionado, é aqui que eu prefiro o evento em si apenas para ir aos objetos por outra interface (seja para um gerente ou por um sistema de mensagens de eventos, se você tem um desses, por exemplo).

Eu acho que você está no caminho certo e só precisa de mais um 'Sim, isso parece certo' Então ... Sim, isso parece certo.

Espero que isto ajude!


3

Normalmente, os mecanismos de jogo usam uma biblioteca de terceiros para detectar colisões entre entidades. Nesse cenário, cria-se ou registra-se as entidades que possuem o PhysicsComponent no mundo "physics". E sempre que detecta uma colisão entre duas entidades (A e B), normalmente chama um retorno de chamada para a entidade A informando que colidiu contra a entidade B e o mesmo para a entidade B, informando que colidiu contra a entidade A.

Para 2D, uma biblioteca de física livre bem conhecida é Box2D. Também vale a pena dar uma olhada no Chipmunk. Para 3D, o Bullet é gratuito (provavelmente o melhor gratuito que você pode encontrar). Havok e PhysX são famosos por serem usados ​​em muitos jogos triplos A.


2

O problema que você está enfrentando é ver que a detecção de colisão (que é a única razão pela qual você precisaria de uma entidade portadora de componente físico para fazer referência a outra) é feita em um nível mais alto, geralmente pelo loop do jogo diretamente ou por uma função / classe auxiliar que faz isso. Minha resposta a alguém, há algumas semanas, fala sobre a remoção de entidades por motivos semelhantes, e tendo em mente que, se uma colisão fizer com que uma de suas entidades seja destruída, essa mesma resposta, em seu contexto específico, será muito relevante para você , já que um "poder superior" ainda terá que gerenciar a limpeza dos corpos ... por assim dizer.

Fazer isso apenas entre entidades, geralmente não é viável. Quase sempre existe um proxy para essas coisas, em uma arquitetura sólida, seja através do gerenciamento direto, como na detecção de colisões, ou despachos de eventos, como em por exemplo. um sistema de mensagens do jogador em que um gerente de mensagens do lado do cliente ouve as mensagens enviadas pelos jogadores e as envia ao servidor para retransmitir a todos.


2

Estou enfrentando exatamente o mesmo problema que você em um projeto agora. O jeito que eu decidi lidar com isso é ter um "ColliderComponent" que retém o corpo do mecanismo de física. Os corpos são definidos externamente (definições de formas que são carregadas em tempo de execução) e, em seguida, adicionados ao mundo da física e às entidades de jogo às quais pertencem.

Estou usando o Box2D, onde você pode anexar um "ouvinte de colisão" que será notificado pela colisão. Como adiciono um ponteiro ao meu "ColliderComponent" nos dados do usuário da empresa, posso obter meus dois ColliderComponents que fizeram parte da colisão.

Portanto, o que acontece quando ocorre uma colisão é o seguinte: Os componentes de colisão que fizeram parte da colisão enviarão uma mensagem ao objeto-proprietário (a entidade do jogo) que, por sua vez, transmitirá essa mensagem a todos os seus componentes.

Cada componente pode reagir a essa mensagem, para que seu "componente de saúde" possa remover 5 pontos da saúde, etc.


+1: estou usando uma abordagem muito semelhante. Como você determina a quantidade de dano a causar, dependendo do tipo de entidade colidida?
Den

@Den Envio mensagens diferentes (ou dados da mensagem) de acordo com a colisão que ocorreu. Isso funciona bem para mim, pois não tenho muitos casos diferentes para tratar.
bummzack

0

Crie um sistema de colisão que conheça o "mundo" da colisão. Em seguida, no componente de colisão, diga ao sistema de colisão para lançar um raio do ponto A ao B e responder se ele colidiu ou não.

Boa sorte. Acho que o sistema de colisão é uma das partes mais entediantes do mecanismo de jogo.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.