Algumas idéias sobre como evitar pesquisas que resultam em caminhos com falha:
ID da ilha
Uma das maneiras mais baratas de concluir efetivamente as pesquisas A * mais rapidamente é não fazer nenhuma pesquisa. Se as áreas forem realmente intransitáveis por todos os agentes, encha cada área com um ID de ilha exclusivo em carga (ou na tubulação). Ao encontrar o caminho, verifique se o ID da Ilha da origem do caminho corresponde ao ID da Ilha do destino. Se eles não corresponderem, não faz sentido fazer a pesquisa - os dois pontos estão em ilhas distintas e não conectadas. Isso ajuda apenas se houver nós realmente intransponíveis para todos os agentes.
Limite do limite superior
Limito o limite superior do número máximo de nós que podem ser pesquisados. Isso ajuda as pesquisas intransitáveis a serem executadas para sempre, mas significa que algumas pesquisas passáveis que são muito longas podem ser perdidas. Esse número precisa ser ajustado e realmente não resolve o problema, mas atenua os custos associados a longas pesquisas.
Se o que você está descobrindo é que está demorando muito , as seguintes técnicas são úteis:
Tornar iterações assíncronas e de limite
Deixe a pesquisa ser executada em um segmento separado ou um pouco em cada quadro, para que o jogo não pare de esperar pela pesquisa. Exiba animação do personagem coçando a cabeça ou batendo os pés, ou o que for apropriado enquanto aguarda o término da pesquisa. Para fazer isso de forma eficaz, eu manteria o estado da pesquisa como um objeto separado e permitiria a existência de vários estados. Quando um caminho é solicitado, pegue um objeto de estado livre e adicione-o à fila de objetos de estado ativo. Na atualização do pathfinding, retire o item ativo da frente da fila e execute A * até que A. seja concluído ou B. algum limite de iterações seja executado. Se concluído, coloque o objeto de estado novamente na lista de objetos de estado livre. Se não tiver sido concluído, coloque-o no final das 'pesquisas ativas' e passe para a próxima.
Escolha as estruturas de dados corretas
Certifique-se de usar as estruturas de dados corretas. Veja como meu StateObject funciona. Todos os meus nós são pré-alocados para um número finito - digamos 1024 ou 2048 - por motivos de desempenho. Eu uso um pool de nós que acelera a alocação de nós e também me permite armazenar índices em vez de ponteiros em minhas estruturas de dados que são u16s (ou u8 se eu tiver 255 nós máximos, o que eu faço em alguns jogos). Para minha busca de caminho, uso uma fila de prioridade para a lista aberta, armazenando ponteiros para objetos Node. Ele é implementado como um heap binário e classifico os valores de ponto flutuante como números inteiros, pois eles sempre são positivos e minha plataforma tem comparações lentas de ponto flutuante. Eu uso uma tabela de hashtags para o meu mapa fechado para acompanhar os nós que visitei. Ele armazena IDs de nó, não nós, para economizar em tamanhos de cache.
Coloque em cache o que você pode
Quando você visita um nó pela primeira vez e calcula a distância até o destino, armazene em cache no nó armazenado no Objeto de Estado. Se você revisitar o nó, use o resultado em cache em vez de calculá-lo novamente. No meu caso, ajuda não ter que fazer uma raiz quadrada nos nós revisitados. Você pode encontrar outros valores que podem ser pré-calculados e armazenados em cache.
Outras áreas que você pode investigar: use o pathfinding bidirecional para pesquisar em qualquer extremidade. Eu não fiz isso, mas como outros observaram, isso pode ajudar, mas não é sem suas ressalvas. A outra coisa na minha lista para tentar é encontrar o caminho hierárquico ou encontrar o caminho do cluster. Há uma descrição interessante na documentação da HavokAI Aqui, descrevendo seu conceito de cluster, que é diferente das implementações HPA * descritas aqui .
Boa sorte e deixe-nos saber o que você encontra.