Um projeto em que estou trabalhando agora apresenta muito "tráfego" no sentido de carros se movendo pelas estradas, aeronaves se movendo em torno de um avental etc.
A partir de agora, os caminhos disponíveis são pré-calculados; portanto, os nós são gerados automaticamente para cruzamentos que são interconectados por arestas. Quando um personagem / agente aparece no mundo, ele inicia em algum nó e encontra o caminho para um nó de destino por meio de um algoritmo simplesmente A *. O agente segue o caminho e, finalmente, chega ao seu destino. Não há problema até agora.
Agora, preciso permitir que os agentes evitem colisões e lidem com situações complexas de tráfego. Como sou novo no campo da IA, procurei vários artigos / artigos sobre comportamento de direção, mas achei que eram de nível muito baixo. Meu problema consiste menos em evitar colisões reais (o que é bastante simples nesse caso, porque os agentes seguem caminhos estritamente definidos), mas em situações como um agente saindo de um beco sem saída, enquanto outro quer entrar exatamente no mesmo. Ou dois agentes se encontrando em um gargalo que permite apenas que um agente passe de cada vez, mas ambos precisam passar por ele (de acordo com a rota ideal encontrada anteriormente) e precisam encontrar uma maneira de deixar o outro passar primeiro. Então, basicamente, o principal aspecto do problema seria prever o movimento do tráfego para evitar bloqueios.
Difícil de descrever, mas acho que você entende o que quero dizer. Você tem alguma recomendação para mim sobre onde começar a procurar? Alguma documentação, projetos de amostra ou coisas semelhantes que possam me ajudar?
Eu aprecio sua ajuda!
Respostas:
Há tantas maneiras de resolver esse problema que eu lutaria para dar uma resposta decente e abrangente aqui. Mas aqui estão alguns pontos de design de alto nível.
Seus sistemas devem se basear em paralelos no mundo real. A razão pela qual a maioria das estradas tem duas ou mais faixas é porque é muito mais fácil organizar o tráfego com esse sistema, ninguém precisa pensar muito. Em um cenário de pista única, os motoristas precisam resolver vários problemas:
detecção - reconhecendo que você e o carro que se aproxima batem, a menos que se evitem
reação - desacelerando e entrando em uma fase de negociação.
negociação - um dos motoristas tem que assumir a liderança, o outro tem que ceder. As regras para decidir isso são vagas, mas basicamente você quer algo em que um motorista arbitrariamente (ou com base em uma heurística sobre quantos carros estão vindo na outra direção) decide ter prioridade. Por exemplo, A tem prioridade no tempo 1, B vê A ter prioridade e produz (saindo do caminho e parando). Se A e B tentarem ter prioridade, ambos deverão parar, aguardar um período aleatório de tempo (ou sinalizar um ao outro) e tentar novamente. Eventualmente, um cederá ao outro.
A vantagem dessa implementação é que ela evita a necessidade de manter filas artificiais ou outras construções falsas. A negociação é feita em termos de percepções do mundo real - uma vez que ambas as partes estão na fase de negociação, qualquer avanço significativo é facilmente detectado como uma tentativa de ter prioridade. Ele também deve reagir adequadamente ao usuário, que provavelmente não seguirá as boas regras de direção.
Suponha o pior. Mesmo em um sistema perfeito, situações estranhas podem surgir e seus atores devem agir com sensatez. Isso é ainda mais provável se o jogador puder interferir (bloquear áreas artificialmente, etc.) Freqüentemente, parar completamente é a única resposta sensata (bloqueio!) Girar no local ou, obviamente, estar em um estado quebrado é uma falha da IA. Parar completamente é pelo menos plausível em termos do mundo real.
Quanto mais você modelar a IA do seu ator na lógica simples do mundo real, mais fácil será criar uma IA convincente. Pessoas reais não param ou oscilam para frente e para trás se não conseguem alcançar seu objetivo. Se o único caminho para o destino da IA estiver bloqueado, eles devem reconhecer isso e escolher uma resposta (pare completamente, desista e volte para casa, desista e dirija para outro lugar).
Comportamentos de camada para obter o que deseja. Lembre-se, o primeiro objetivo não é falhar. Portanto, a lógica da prevenção (direção) deve sempre dominar as ações do motorista. Coloque em cima disso a lógica direcional que vem da descoberta do caminho ('eu quero virar à direita no próximo cruzamento'). Camada sobre essa ocasional reavaliação de caminhos, com lógica de nível superior ('prefere avançar, mas se eu não puder progredir, permita um novo caminho que envolva uma inversão de marcha').
A descoberta de caminhos vem da memória, mas a consciência situacional é baseada na percepção. Não tente fazer seus agentes perfeitos. Eles sabem o caminho de casa para o escritório, para saber quais são as voltas a serem feitas. Mas eles não sabem que a rua a 3 km está bloqueada. Não tente fazer com que seus agentes planejem um caminho perfeito, porque não há nenhum - mesmo que comece perfeito, outros fatores podem bloquear seu caminho. Os agentes só precisam planejar algumas ruas à frente para onde estão indo.
Qualidade da informação. Seus comportamentos devem ser simples, mas para conseguir isso, você precisa de uma boa funcionalidade de consulta. Você precisa fazer perguntas ao seu ambiente como "esse carro está ocupando minha pista?", "Quantos carros estão chegando?", "Existem carros atrás de mim", "posso fazer uma inversão de marcha" .
fonte
Tendo visto algumas falhas horríveis nos jogos lançados, tenho algumas sugestões:
1) A menos que haja uma boa razão, faça duas faixas e, para fins de IA, faça com que elas tenham prioridade para uma direção normal do fluxo - permita viagens de duas a duas, mas se algo estiver vindo para o outro lado, o cara do lado errado da estrada sempre cede a ele.
2) Algum tipo de lógica para resolver um engarrafamento, se ocorrer. Eu assisti situações em que o manuseio do engarrafamento se aplicava apenas aos veículos que estavam tentando se encontrar, mas que falharam totalmente quando confrontados com um padrão -> -> <- <-. Lembro-me de um mapa que era propenso a isso - era um ponto de estrangulamento destinado a tornar a base da IA mais difícil de atacar, mas mais cedo ou mais tarde dois coletores de recursos chegariam enquanto um grupo de ataque estava saindo e foi isso. As unidades em contato giravam ao redor, tentando encontrar uma rota, mas não tinham movimentos legais. Ele não voltou atrás e descobriu que alguma outra unidade tinha que se mover primeiro e, portanto, a IA não tomou ações úteis até que o bloqueio fosse removido. (Você pode assistir as unidades em contato girando e nada mais faz nada.)
Acredito que isso poderia ser resolvido, fazendo uma unidade presa dizer às unidades vizinhas que se afastassem - isso se propagaria até chegar a uma unidade livre que pudesse recuar. Isso teria que envolver algum tipo de lógica para mantê-los afastados até que o problema fosse resolvido.
Observe que simplesmente procurar um caminho alternativo geralmente é uma resposta ruim. Eu assisti a uma situação de livelock desse tipo - a unidade A observa que B está bloqueando a estrada à frente e, portanto, ela se vira para usar uma rota diferente. Isso agora bloqueia a estrada para B que se vira - agora a estrada está desbloqueada, então as duas se viram novamente. Cada turno alternam entre avançar e recuar.
O mesmo jogo que eu já vi uma versão diferente, também devido ao nevoeiro da guerra. Havia uma unidade inimiga no ponto de estrangulamento. Ao mover-se automaticamente, a busca de caminhos não lutaria, a menos que seja realmente direcionada à unidade inimiga. Ele avançaria e veria a estrada bloqueada. Depois voltou, não pôde mais ver o bloqueador e seguiu em frente novamente. Repita até o humano perceber que não estava chegando aonde deveria ir.
fonte
Não tenho muita experiência com simulações de tráfego, mas algumas coisas vêm à mente.
Em primeiro lugar, para evitar gargalos, em primeiro lugar, eu teria duas faixas que permitem que os veículos viajem em direções opostas. na mesma "estrada".
Em segundo lugar, para colisões que possam ocorrer, você deve ter um comportamento de direção de prevenção de colisões para evitar uma acumulação maciça. Os comportamentos de direção podem ser de baixo nível, mas são muito úteis na criação de comportamentos emergentes com aparência realista.
Se você não quiser ter mais de uma faixa, precisará armazenar mais informações no gráfico. Por exemplo, se o agente A estiver em uma estrada (representada como uma aresta do gráfico) e o agente B estiver na mesma estrada, movendo-se na direção oposta a A, eles serão colidir / impasse / whatever que você codificado para lidar com esse comportamento.
No entanto, se o agente A estiver em uma estrada, ele poderá solicitar a propriedade dessa estrada. Possuir a estrada significaria que nenhum outro agente pode viajar ao longo dessa borda (você pode fazer isso simplesmente alterando o custo da borda para um número enorme para garantir que A * não escolha a estrada ao calcular um caminho). Então, quando o agente A está livre dessa estrada, ele renuncia à propriedade.
Honestamente, é uma solução hacky da qual não gosto particularmente e a maioria das simulações de tráfego (se não todas?) Que vi usar uma abordagem de várias faixas.
fonte
Você disse que procurou vários artigos sobre comportamento de direção, embora apenas no caso, você procurou no seguinte?
http://www.red3d.com/cwr/steer/
Caso contrário, poderá fornecer algumas respostas, pois abrange alguns dos problemas que você nomeou, por exemplo, o problema de gargalo (enfileiramento).
fonte
Eu acho que o que você precisa fazer é implementar um algoritmo de localização de caminho.
Divida o mapa em pedaços tão pequenos quanto possível (digamos quadrados), mas apenas para lugares válidos para o tráfego viajar. Você determinaria onde o veículo está e para onde está indo e encontraria um caminho, mais curto ou mais direto, talvez. O caminho será uma matriz de quadrados, a cada passo do caminho para a destruição. O que você deseja então é calcular não apenas a posição atual de todos os veículos, mas também as posições futuras dos veículos para algumas etapas no futuro. Se dois veículos estiverem no mesmo quadrado no futuro, você precisará alterar a velocidade de um ou de ambos.
A * (Uma estrela) é um algoritmo de localização de caminho muito simples que você provavelmente pode facilmente traduzir o código psuedo na wikipedia para o seu idioma preferido e funcionará: http://en.wikipedia.org/wiki/A*_search_algorithm
fonte
Quando eu implementei o Inemy Nations, meu retorno final foi que, se um veículo permaneceu preso por mais de 2 segundos, eu pulei para frente em seu caminho. Então, quando eles ficaram presos, uma unidade basicamente transportada. Ninguém nunca reclamou, então eu acho que nas poucas vezes que isso aconteceu, ninguém estava assistindo e não viu.
fonte