A maneira mais simples de criar um NPC que toma decisões sobre o que fazer, com base na
localização do jogador, é a Linha de Visão.
O Line Of Sight funciona calculando o ângulo e a distância do PNJ ao jogador e
usando esses dados para decidir sobre a ação a ser tomada.
É uma maneira muito fácil de criar um agente puramente reativo, cujo comportamento é determinado pela capacidade de ver
ou não o jogador.
Para implementar isso, o NPC recebe um campo de visão.
Este é um cone que se estende desde a localização do NPC em sua direção voltada para a frente, pelo comprimento de
seu alcance visível e se espalhando por um ângulo de visão. Para determinar se um jogador cai dentro
deste cone, calculamos o vetor do NPC para o jogador.
Depois, determinamos se a 'distância do jogador' é menor que o 'alcance visível' e se o 'ângulo da
posição do jogador' é menor que o do 'ângulo de visão'. Se ambas as condições forem verdadeiras, o jogador estará visível
para o NPC.
Acompanhe como eu mostro como configurar esse tipo de NPC de linha de visão. Faça o download do AIRobotGuard. unitypackage que acompanha
esta palestra.
Crie um novo projeto do Unity 3D e arraste e solte esse arquivo de pacote em seus ativos.
Ao fazê-lo, você receberá esses 2 itens. Você obterá uma cena chamada RobotGuard (que você pode abrir
e verá o guarda do robô em pé na cena) e uma pasta com seu trabalho artístico.
Os outros itens, você vai adicionar.
Então, quando você estiver pronto, adicionaremos um controlador em primeira pessoa, para que possamos andar
por aí e testar nossa proximidade com o NPC.
Vá para 'Assets> Import Package' e traga o pacote 'Characters'. Esse é o da
primeira pessoa, terceira pessoa etc. coisas nele, então traga todos esses itens e
isso lhe dará uma pasta de Ativos Padrão na qual você
encontrará Personagens e, em seguida, queremos a primeira pessoa 'Prefabs' e o FPSController.
Então segure-o, arraste-o
para a cena e apenas levante-o para que fique acima do solo.
Agora que você tiver feito isso, ela terá sua própria câmera.
Portanto, a câmera que está em cena, você pode excluir (ou simplesmente desligar).
Agora, para testar se está funcionando, basta pressionar Play e você poderá passear pelo ambiente ...
Curtiu isso.
Está bem.
Pressione a tecla Esc para recuperar o mouse e parar de jogar.
Está bem.
Então, de volta ao Assets, vamos criar um script AIController.
Eu já tenho um aqui, mas você deseja 'Criar> Script C #' e chamá-lo de AIController. Dentro desse script, você
adicionará isso.
Portanto, este é o script básico para que nossa Linha de Visão funcione.
Primeiro de tudo, precisamos saber onde o jogador está, então teremos uma transformação
pública no topo para passar pelo jogador.
Em seguida, temos várias variáveis sobre o comportamento do próprio NPC.
Portanto, temos o usual "rotationSpeed" e "speed" para girar e mover o personagem e, em seguida, temos os valores da Linha de
Visão.
Portanto, temos uma distância visível (portanto, a que distância do personagem ele pode detectar o jogador, neste
caso, é 20), o ângulo
visível é definido como 30 (para que você possa ver a uma distância de 20, dentro de um ângulo de 30 graus para ambos
os lados.
Portanto, esse ângulo é como metade do campo de visão completo, que seria 60).
Então temos uma distância de tiro e a distância de tiro é a que distância o personagem deve estar para
começar a atirar.
Portanto, se não estiver perto o suficiente e o detectou, pode ocorrer até você estar perto o suficiente
para tirar uma foto.
Em seguida, armazenaremos um estado e esse estado nos ajudará a determinar quais animações serão
executadas um pouco mais tarde. Portanto, o NPC terá três estados, terá IDLE, terá RUNNING e terá SHOOTING
e você os verá entrar em jogo na atualização.
Agora, na Atualização, é onde todo o trabalho está acontecendo.
A primeira coisa que fazemos é calcular a direção do NPC para o jogador. Ok, lembre-se, para fazer isso, é o NPC
retirado da posição do jogador e isso lhe dará seu vetor de direção.
Depois, calculamos o ângulo entre esse vetor de direção e o vetor voltado para a frente do NPC e podemos fazer isso
com o nosso Vector3. Método de ângulo.
Então isso nos dá um ângulo em graus.
Depois disso, faremos uma instrução if para testar se o comprimento desse vetor de direção está
dentro do nosso alcance visível e nosso ângulo é menor que o ângulo visível, então estamos prontos para prosseguir.
Depois disso, estou definindo os vetores de direção 'y' para 0.
Portanto, o vetor de direção será em 3 dimensões.
Se seu personagem for maior ou menor que o robô, ter um valor y diferente fará com que ele se incline e se você não
quiser que se incline para cima ou para baixo para olhar para seu personagem, você
quer que ele fique fundamentado em y -axis
sempre voltado para cima, é uma boa ideia definir essa alteração no 'y' sempre de volta para 0 depois de fazer o cálculo.
Confie em mim, isso vai manter tudo na horizontal.
Em seguida, configuramos a rotação do NPC com um slerp (como fizemos no passado) para deslizar gradualmente em direção ao vetor
de direção, usando o nosso rotationSpeed.
Portanto, com este código, se o jogador estiver dentro do alcance visível do NPC, ele sempre estará voltado para ele.
Então nós apenas temos que decidir se vamos empurrar o NPC para frente, em direção ao jogador.
Então
aqui embaixo, depois
disso, temos 'if (direção. magnitude> shootDist) ', o que significa que
estamos fora do alcance para atirar, mas ainda estamos dentro do alcance para correr atrás do personagem (porque isso
está dentro dessa declaração if aqui em cima),
portanto, se não podemos atirar, então vamos correr em direção ao jogador, caso
contrário, vamos atirar e, portanto, estamos
definindo esse valor de 'estado'.
Se o jogador estiver fora do nosso alcance, basta definir o estado como IDLE com esse 'mais' aqui,
para garantir que você tenha essa declaração if correta, caso
contrário, isso dará errado para você.
Então, depois disso (e fora dessa
instrução if-else, temos um 'if (state == "RUNNING")' e, em seguida, empurre o caractere para frente, nesta linha aqui.
Portanto, é a única vez que você deseja Traduzir o personagem, quando está
no estado RUNNING, caso contrário, fica parado (Ocioso) ou TIRO.
Certo, salve isso, volte para o Unity e adicionaremos
esse código (arraste e solte-o no seu robô), selecione o robô, descubra
onde está o código e onde 'Player' está exposto, arraste e solte seu FPSController
nele, para que o A. EU. sabe sobre isso.
Tudo certo.
Vamos testar isso.
Pressione Play e, se olharmos em volta e encontrarmos o robô ...
ali está ele.
Agora, suas animações não vão funcionar neste momento.
Só queremos verificar, se nos afastarmos, perceber como
ele está nos seguindo.
Este é ele nos perseguindo e
quando ele chegar perto o suficiente, ele irá parar e então ele
irá para o tiroteio e se nos virarmos, ele também continuará se voltando para nós.
Portanto, deve haver um ponto (se pudermos ficar fora do alcance dele) de
que ele realmente
parará de se mover, o que está por aí; se ficarmos fora do alcance e caminharmos atrás dele (fora do ângulo visível),
deveríamos estar capaz de esgueirar-se de lado e ele não vai nos detectar.
Então ele não está nos detectando porque não está se virando para nós, mas se nos movermos dentro do alcance (vamos sair aqui) lá, ele nos detectou,
virou-se para nós e começou a se mover ao nosso alcance.
Ok, essa é a lógica básica dessa linha de visão.
Agora que a lógica da Linha de Visão está lá, podemos adicionar as animações.
Agora, o robô que lhe dei tem animações e está pronto para ser usado.
Se você clicar no robô, verá que ele possui um Animador no Inspetor.
Se você clicar duas vezes no RobotGuard, ele abrirá a janela do Animator e você poderá ver o que
está lá.
É muito simples.
Ele é configurado de maneira bem parecida com as coisas que usamos antes e basicamente são
os estados de
animação, 'ocioso', 'executado' e 'disparado', e todos estão ligados por transições e gatilhos nessas transições.
Então, eu as configurei, há um 'isRunning' e 'isShooting' e
um 'isIdle' e todos eles se vinculam entre esses estados de animação.
Portanto, não há nada que você precise fazer para isso, no que diz respeito à
configuração, mas o que faremos é acioná-los no código com base no estado em que o NPC está. A propósito, esse modelo de robô em particular veio com
um projeto do Unity há muitos e muitos anos e nem me
lembro qual versão era.
Talvez um de vocês se lembre. Talvez tenha sido a versão 2 ou
algo assim, porque essas animações eram animações herdadas, então atualizei as para o sistema mecanim.
Então, vamos voltar ao código, voltar à nossa cena lá ... Ativos e abra o código.
A primeira coisa que precisamos fazer (como sempre) é agarrar seu animador.
Então, configuramos isso no topo e, em seguida, no Start, agarramos-no, então 'anim = this. GetComponent 'para o Animator, assim e
depois temos que
definir os gatilhos junto com cada estado.
Então, na atualização, vamos ao primeiro para RUNNING.
Agora aqui, podemos colocar 'anim. SetTrigger ("isRunning"); ' - lembre-se de soletrar seus gatilhos e colocar letras maiúsculas
exatamente da mesma maneira que são configuradas nos parâmetros no Animator.
Agora isso definirá o gatilho para fazer com que a animação 'isRunning' funcione.
O único problema de fazê-lo dessa maneira é que, se o personagem já estiver em execução, ele será
reativado, reativado e
reativado, e você poderá acabar com coisas estranhas acontecendo com vários disparos.
Para que possamos testar ... 'if (estado! = "RUNNING") ', então definiremos o estado como RUNNING e o
gatilho para' isRunning '.
Portanto, isso indica que, se você não estiver executando, comece a
executar e, se já estiver executando, não há necessidade de começar a executar novamente.
A mesma coisa para todos esses outros, então faremos o mesmo com as filmagens. Então é 'if
(estado! = "TIRO") ','
state = "TIRO"; e 'anim. SetTrigger ("isShooting"); '
e mais uma vez, ocioso.
Portanto, agora isso definirá nossas animações com base no estado e garantirá que elas não sejam definidas
duas vezes seguidas e logo na parte inferior, do
lado de fora, se as estiver executando, ainda executaremos
nosso avanço Tradução.
Tudo bem, então salve
isso e vamos voltar e experimentar.
Então, pressione Play ... ele vai começar a atirar (o que é porque estamos bem
ao lado dele) e agora, se ficarmos fora do alcance, ele
vai correr atrás de nós e começar a atirar (eu vou fazer minha janela de jogo um pouco maior) e se eu conseguir ficar fora
do alcance, ele perderá o interesse e voltará ao estado ocioso
que você pode
ver lá e poderemos ...
esgueirar-se e porque não estamos dentro desse intervalo, ele não está
nos notando e eu posso me virar ... volte ao alcance e ele começará
a atirar e nos perseguir e se virarmos enquanto estivermos ao alcance, ele irá virar.
Então isso é muito
simples A. EU. mecânica chamada Line Of Sight, para fazer seu NPC perseguir o jogador com base
em uma variedade de visibilidade.