Como devo implementar a "consciência" inimiga das unidades?

12

Estou usando o Unity3d para desenvolver um jogo de protótipo híbrido RTS / TD. Qual é a melhor abordagem para "conscientização" entre as unidades e seus inimigos? É lógico que todas as unidades verifiquem a distância de todos os inimigos e se envolvam se estiverem dentro do alcance?

A abordagem que eu estou adotando agora é ter uma esfera de gatilho em todas as unidades. Se um inimigo entra no gatilho, a unidade fica ciente do inimigo e inicia a verificação da distância. Isso economiza algumas verificações desnecessárias?

Qual é a melhor prática aqui?

Phil
fonte
Devo acrescentar que a contagem de unidades / inimigos estará na escala do Supremo Comandante
Phil

Respostas:

10

Examine as hierarquias de volume delimitadoras (BVH). Eles são mais comumente usados ​​na detecção de colisões para reduzir o número de verificações necessárias ao calcular colisões ou na renderização para realizar o descarte de objetos em objetos. Como você já está usando esferas, sugiro uma árvore de esferas, embora outros volumes, como os AABBs, possam ser mais eficientes. Não sei ao certo que tipo de suporte o Unity tem para coisas como nunca o usei, mas provavelmente já há algo para isso na detecção de colisões ou na renderização de partes do mecanismo.

Basicamente, você gostaria de agrupar inimigos que estão próximos um do outro em várias esferas parentais. Quando uma unidade é movida, você confere sua esfera de disparo contra a esfera pai em vez de verificar cada inimigo. Se a esfera do gatilho se cruzar com a esfera pai, você verificaria cada inimigo dentro. Caso contrário, você pode descartar todos os inimigos que estiverem nele. Você deseja configurar vários níveis de esferas com base no tamanho máximo da esfera ou na contagem de inimigos para cada esfera e executar a verificação com base em uma esfera de nível superior. Então é só uma questão de descer a árvore para verificar cada inimigo sem precisar executar a verificação de distância de cada um.

Etapas necessárias para cada quadro:

  1. Mover inimigos
  2. Reconstruir / atualizar o BVH para novas posições inimigas
  3. Mova as unidades e verifique a árvore de esfera.

Isso pode reduzir as verificações necessárias quando há muitos inimigos, mas a sobrecarga de atualização e armazenamento da árvore pode não valer a pena quando não há muitas. Eu não estou familiarizado com o Comandante Supremo para saber o que você está procurando, então estou apenas assumindo 'centenas'. Você precisará criar um perfil em diferentes situações para descobrir se a sobrecarga valerá a pena para você.

Joel Baker
fonte
3
+1 essa abordagem será mais simples, embora haja alguns erros. O OP pode querer implementar isso e, em seguida, implementar algo como uma octree. Além disso, na maioria dos RTSs, as unidades reagem com algum atraso. De fato, a maior parte da IA ​​em jogos é calculada em 10 a 30 quadros por segundo, onde o jogo pode ser executado em 30 a 60 quadros por segundo (os números são, é claro, aproximações).
Samaursa
Obrigado, era exatamente isso que eu precisava para me levar um passo adiante. Vou procurar o BVH e como implementá-lo no Unity. Post muito pedagógico e informativo! 1
Phil
Ah, e confira o Supreme Commander se você estiver no RTS. É realmente um jogo muito bom, assim como todos os jogos de Chris Taylor.
Phil
7

Não há necessidade de implementar os BVHs, pois o mecanismo de colisão do Unity já faz isso por você.

Basta conectar um gatilho grande de esfera delimitadora a cada unidade (representando seu alcance) e manipular os retornos de chamada OnCollisionEnter()e OnCollisionExit()para acompanhar quais inimigos estão ao alcance de cada unidade.

Observe que o caso em que você está interessado é quando outra unidade colide com a esfera, não quando a esfera de outra unidade colide com a esfera.

BlueRaja - Danny Pflughoeft
fonte
1
Eu acho que isso precisa ser votado pelo menos um pouco acima da resposta aceita. A resposta aceita é boa para estudar, mas essa resposta deve estar no topo, pois é a maneira mais prática.
Varaquilex
Eu acredito que você quer dizer OnTriggerEnter()e OnTriggerExit(), certo?
Jibb Inteligente
1

Outra solução que se adapta muito bem e pode ser usada para várias outras coisas é um mapa insuficiente. Gere um conjunto de blocos de grade ao redor da unidade para digitalizar dentro do raio X. Examine essas peças para encontrar um inimigo em pé em uma delas. Se você deseja obter os inimigos mais próximos, pode classificar seu conjunto por distância.

Esse pode ser o método mais eficiente, especialmente se você planeja fazer outras coisas com o mapa de influência, como neblina de guerra ou busca de caminhos.

Aqui está um vídeo que eu fiz explicando o conceito: https://www.youtube.com/watch?v=MEd6XV2Pecw .

E aqui está uma implementação: https://www.youtube.com/watch?v=y_ewoxlZlgc

Eu recomendo não inicializar a coleção de unidades do bloco de grade na inicialização - mas apenas quando a coleção for necessária.

Como alternativa, você pode usar uma matriz de comprimento X se souber que nunca haverá mais de X unidades em um bloco.

JPtheK9
fonte