Oi. Bem-vindo de volta a este tutorial, abordando como criar uma máquina de estado finito de NPCs.
Até agora, criamos a Patrulha para o nosso pequeno tanque verde.
Vamos agora criar o Chase, no entanto, antes de começarmos a fazer isso, quero criar uma Classe Base para
nossas máquinas de estado, porque precisaremos ter informações sobre onde o jogador está e onde está o NPC,
para descobrir distâncias e ângulos e coisas assim, e podemos fazer isso em cada um de nossos comportamentos de máquina
de estado que adicionamos, mas teremos que continuar fazendo isso repetidamente.
Portanto, se criarmos uma classe base, poderemos colocar todas essas informações apenas uma vez.
Então vamos ao Ativos e ao nosso projeto. Vamos criar outro script C # - vamos
chamá-lo de NPCBaseFSM.
Está bem.
Agora abra isso e adicionaremos esse código.
Então observe que não é um MonoBehaviour, é um StateMachineBehaviour e
é NPCBaseFSM Dentro daqui, vou configurar um link para o nosso NPC e também para o nosso oponente, e também
vou colocar algumas propriedades para velocidade, velocidade de rotação e precisão, para que possamos
alterá-las como quisermos, em vez de codificá-las no código anterior.
Agora, a função que realmente estamos interessados em substituir e estamos usando é OnStateEnter.
Então, toda vez que entramos em um estado, queremos agarrar o NPC e o oponente e você notará que o
oponente aqui está recebendo um componente que está anexado ao próprio NPC chamado TankAI e escreveremos esse momento em um momento, mas
isso está se apoderando do jogador e informaremos o personagem do tanque sobre o jogador real, para que
ele possa girar, atirar e avançar em direção a ele e esse tipo de
coisa.
Portanto, esta é a nossa Classe Base e, como ainda não temos esse script TankAI gravado, você receberá um erro
dizendo que ele não pode ser encontrado quando você o salva.
Então, vamos escrever esse script TankAI agora.
Então, de volta ao nosso projeto, vamos criar outro arquivo C # e chamá-lo TankAI,
abri-lo e, neste código, adicionaremos isso.
Portanto, o início desse script TankAI é que ele tem um link para o player e,
em seguida, temos uma chamada de método público 'GetPlayer', que você viu chamada anteriormente, do nosso código anterior
e retornará o 'player'.
Então, podemos usar isso para determinar a distância entre o tanque e o jogador um pouco mais tarde.
Portanto, salve isso e volte
para o Unity, o que você quer fazer com esse código é arrastar e soltar no Tank. Selecione o tanque na hierarquia e você
verá o script em anexo.
Agora ele tem o espaço Player aqui, a variável exposta que criamos.
Arraste seu Player da Hierarquia para esse espaço, para que agora ele saiba e esteja vinculado a ele, ele será
capaz de determinar a distância.
Agora, com essa nova Classe Base, precisamos consertar nossa Patrulha, então abra sua Patrulha
e, em vez de herdar do StateMachineBehaviour, herdaremos do NPCBaseFSM e isso incluirá nosso NPC,
por isso não precisamos disso ... podemos removê-lo de dentro daqui.
Também podemos remover a configuração daqui, porque ela já está acontecendo em nosso OnStateEnter, que está de
volta em nossa Classe
Base, mas para garantir a execução, precisamos chamá-la.
Então, vamos adicionar uma linha de código e, para retornar às classes base OnStateEnter, chamamos base. OnStateEnter e passe pelos mesmos parâmetros
que estão chegando até aqui e que configurarão
nosso NPC.
Agora o NPC é usado em nosso OnStateUpdate e já está lá.
As coisas que precisamos mudar
aqui, lembra que adicionamos precisão, velocidade e velocidade de rotação?
Então, na rotação aqui, podemos colocar nosso rotSpeed lá (que é proveniente dessa classe, lembre-se no
topo.
Temos velocidade, velocidade de rotação e precisão) e isso aqui vai ser velocidade e, em
seguida, nossa precisão é usada aqui para determinar se precisamos ir para o próximo waypoint, então vamos mudar
isso para precisão.
Agora, se você usar esses valores para qualquer outra coisa no seu código,
poderá voltar aqui e alterá-los para o seu NPC.
Neste ponto, provavelmente vale a pena salvar tudo e apenas testar se ele
ainda funciona, então vamos apenas pressionar Play e o código de patrulha ainda está funcionando.
Tudo bem, então vamos continuar com o funcionamento do nosso estado Chase. No seu Animator, crie um novo estado.
Portanto, clique com o botão direito do mouse em> Criar estado> Vazio e chamaremos isso de 'Chase',
então vá até o Inspetor e dê um novo nome a ele. Agora 'Chase' será transferido para o Patrol, então clique com o botão direito do mouse em Patrol e
vá em 'Make Transition'.
Você receberá uma pequena seta na qual poderá clicar em outra coisa. Você deseja clicar nele
para 'Chase'.
Essa é a
sua transição e, se você a selecionar, verá no Inspetor, um local onde podemos adicionar nossas condições.
A outra coisa a ser observada aqui também, é 'Tem hora de saída'. O tempo de saída tem que esperar até que a
patrulha termine
o que estiver fazendo em sua atualização para fazer a transição para o Chase.
Agora, se você quiser que ele seja interrompido completamente, livre-se, desmarque-o e não espere
mais.
Portanto, se você achar que há lags entre a transição, será porque você ainda tem esse tempo de saída marcado
em todas as suas transições e cabe a você decidir se deseja ou não.
Agora, a condição para ir de Patrulha em Chase, digamos que será quando o jogador chegar
a uma distância de 20 unidades.
Então, precisamos de um parâmetro aqui para 'distance'.
Então, no Animator, ao lado, há uma guia Camadas e um Parâmetros. Você deseja clicar em Parâmetros e depois há um pequeno
sinal de +, clique nele ... vamos adicionar um flutuador.
Então adicione um float e chamaremos de 'distância'.
Inicialmente, queremos que o NPC esteja muito longe do jogador.
Não queremos que isso seja acionado imediatamente, portanto, se 'distância' estiver definida como 0, isso será acionado imediatamente.
Vamos configurá-lo para algo ridículo como 100, que está totalmente fora do domínio e,
em seguida, o que fazemos aqui na transição é clicar nele. Lá no Inspetor, em Condições, pressione o + e ele aparecerá
imediatamente com a distância, porque é a
única coisa que ele conhece e depois 'Maior' que 0. Estamos dizendo que essa condição é 'a distância é menor que 20'.
Então, vamos colocar um 20 lá.
Portanto, quando esse valor chegar a menos de 20, a transição ocorrerá e o estado Chase será iniciado.
A próxima coisa que precisamos fazer é atualizar qual é
a distância aqui, caso contrário ela nunca
ficará abaixo de 20 e a distância será baseada na distância entre nós (nosso jogador) e nosso NPC.
Agora você pode calcular a distância entre o jogador e o NPC dentro da sua
máquina de estado, mas deseja fazer isso repetidamente e é uma condição usada em
toda a máquina de estado e, portanto, faz
sentido fazê-lo externamente. isso e
o código para isso irão para o TankAI. Fazer isso dessa maneira também mostrará como injetar um valor do seu MonoBehaviour
no sistema de animação para que você possa alterar essa condição.
Primeiro, no script TankAI, você precisará agarrar o animador, portanto, criaremos um 'anim' de animador no topo aqui
e,
em seguida, na função Iniciar, configuramos isso para que ele aponte para o Animator que está anexado ao seu
objeto de jogo (ou ao tanque,
neste caso), portanto será anim = GetComponent para o Animator ... Curtiu isso.
Então agora você tem seu Animator configurado.
Agora, a distância é calculada entre este objeto (o tanque) e o jogador que você encontrou aqui,
para que você possa injetar esse valor de 'distância' na atualização, para que você possa constantemente trabalhar a distância
e enviá-la através para a máquina de estado.
Então, no
Update, vamos adicionar este pedaço de código ... e o que está fazendo é pegar o Animator e chamar
o método SetFloat.
O que isso fará é definir o valor da distância (verifique se
está entre aspas aqui e se está escrito exatamente o mesmo que você tem seu parâmetro lá em cima porque se refere
a isso) e, em seguida, o que você colocar na próxima parte do método será o valor para o
qual ele será alterado.
Estou usando um Vector3. Distância para calcular a distância entre a posição do nosso
tanque e a posição do jogador.
Então, vamos dar uma olhada em como isso funciona.
Salve isso e volte para o Unity e pressione Play.
Agora, se você olhar aqui à distância (enquanto isso está tocando), verá que isso muda e é porque
o tanque está se movendo.
Você também notou que houve uma transição quando essa distância ficou abaixo de 20.
Então, vamos jogar de novo e assistir.
Então, eu vou mover o jogador dessa vez e, quando chegar aos 20, a transição para o Chase acontece e
fica presa nesse Chase porque não há outro lugar para ir.
Também não há código adicionado como comportamento lá, então o tanque não fará nada, mas sabemos
que foi acionado porque vimos aqui e vimos o tanque parar.
Então, adicione um código de comportamento ao Chase, selecione Chase no Animator e vá até o Inspector ...
clique em [Adicionar comportamento] ...
desta vez, será chamado 'Chase', [Create and Add] e você verá o Chase aparecer no final
e vamos abrir e, para o Chase, vamos abrir os mesmos métodos que tivemos antes
na Patrulha e adicione algum código à Atualização.
Chase agora se parece com isso
(e deixe-me mostrar isso).
Você só está perdendo
os cantos irregulares, mas apenas para ver o código completamente. O Chase herdará do NPCBaseFSM para obter os detalhes sobre
o NPC e o OnStateEnter chamará nossa base. OnStateEnter novamente, a fim de configurá-lo
novamente, porque lembre-se, isso não passará da Patrulha, porque, no que diz respeito
a eles, eles nem se conhecem, por isso não
há como isso, a menos que obtenha da base.
Agora temos nosso OnStateUpdate que fará todo o trabalho aqui e tudo o que
está fazendo é apenas configurar o código Chase, que fará com que o tanque vire para o jogador e siga o tanque do jogador.
Então, antes de tudo, você precisa descobrir qual é a direção entre o oponente (que é o jogador)
e o próprio NPC.
Essa é a direção.
Em seguida, avançamos nessa direção usando nosso rotSpeed que temos dentro da nossa Classe Base e, em seguida,
executamos um Translate aqui com base na velocidade ao longo do vetor para frente do tanque.
Esse código de movimento aqui é praticamente o mesmo que temos para virar em direção
aos waypoints e empurrar o NPC nessa direção.
Tudo certo.
Salve tudo isso e, em seguida, volte para o Unity e podemos tentar isso.
O que deve acontecer é que vamos 'patrulhar' até chegar a uma distância
menor que 20 e então a 'perseguição' começará e, na perseguição, o tanque continuará seguindo o nosso jogador, então
vamos levar o jogador até lá
e nós agora
está no modo de perseguição e, se eu continuar movendo meu jogador, você verá que ele o seguirá e seguirá
para sempre, porque não há como voltar à Patrulha, mas isso é facilmente corrigido,
porque todos os código está no lugar para isso.
Então, vamos parar de tocar e fazer a transição de Chase para Patrol, quando a distância se tornar maior
que 20, então queremos que o tanque volte para Patrol.
Então clique com o botão direito do mouse em Chase, Make Transition e solte a seta em Patrol,
selecione a seta
e depois vamos para o Inspector, desmarque 'Has Exit Time' e adicione a condição de 'distance maior que 20'.
Então agora temos ... menos de
20 passaremos de Patrulha para Chase e, em seguida,
maiores que 20, voltaremos a patrulhar e, como esses comportamentos estatais são configurados aqui,
é tão simples quanto possível.
Estamos apenas injetando a distância constantemente do TankAI
e da máquina de estado fazendo o resto do trabalho. Então, pressione Play e eu moverei meu tanque.
Então, agora estamos no modo Chase ... e o tanque vai seguir e virar em direção ao meu jogador ...
mas se eu for embora ... e ultrapasse os 20, a patrulha retornará e o tanque voltará a
patrulhar e lembre-se de que o
OnStateEnter for Patrol faz com que o tanque retorne ao primeiro waypoint todas as vezes em sua configuração.
OK, então está preparando o assunto. No próximo tutorial,
veremos como adicionar 'Ataque'.