No workshop Line of Sight, montamos uma variável chamada 'state' para acompanhar a atividade que o NPC
estava executando no momento. UMA. EU. Os métodos que usam estados são muito comuns
na programação de NPC e não são mais focados do que no caso de Máquinas de Estados Finitos.
Nesta palestra, vamos construir uma Máquina de Estado Finito do zero e usá-la para
controlar um tanque que executará funções de 'guarda' e 'perseguição'.
Uma Máquina de Estado Finito é uma máquina conceitual que pode estar em exatamente 1 de qualquer
número determinado de estados finitos a qualquer momento. Uma Máquina de Estado Finito é usada no campo da Inteligência
Artificial para definir (entre outras coisas) os comportamentos de caracteres controlados por computador. É representado como um gráfico com nós que representam os estados
e transições, que definem o caminho de um nó para o próximo. Depois que um estado é inserido, o NPC
permanece
nesse estado até que uma condição na transição seja atendida.
Aqui temos uma máquina de estado finito para um comportamento simples de proteção.
Se o NPC estiver no estado Patrulha, ele continuará executando os comportamentos associados até que uma condição seja
atendida em qualquer uma das transições que saem do estado.
Nesse caso, ele aguarda até que o jogador esteja a uma distância inferior a 20.
Quando essa condição é atendida, o NPC transita para o estado Chase. Se você está usando o Unity e acha que o conceito de
Máquina de Estado Finito parece familiar, é porque é! O sistema mecanim usa máquinas de estado finito
para controlar comportamentos de animação e é exatamente isso que estamos prestes a usar para definir o comportamento
do pequeno tanque verde. Para acompanhar como eu construo
este F. S. M. , faça o download do arquivo inicial que acompanha esta palestra.
Isso usa muitos recursos do tutorial de tanques que o Unity lançou há alguns anos
e eu os adaptei novamente para usá-los nessa situação.
Quando você abrir a cena chamada Tanks pela primeira vez, verá isso. Portanto, temos um pequeno tanque verde que será nosso NPC e temos
um tanque que podemos dirigir - ele já possui um script. Se você pressionar Play, poderá usar as
setas do teclado para movê-lo ... Curtiu isso.
A primeira coisa que precisamos fazer para o nosso tanque verde é criar um controlador de animação.
Então entre no projeto e clique em Criar e você está procurando pelo Animator Controller, que está fora da minha
lista aqui.
Deixe-me trazer isso para você ... Crie> Controlador do Animator.
Se você já usou animação antes no Unity, estará familiarizado com isso.
Vamos chamar isso de nosso NPCFSM, assim. Para começar a criar os estados, clique duas
vezes no NPCFSM e isso abrirá a janela do Animator.
O primeiro estado que criaremos é o Patrol. Clique com o botão direito do mouse na janela do Animator,
vá em 'Criar estado> Vazio', selecione esse estado e, no Inspetor, você pode alterar o nome.
Em vez de atribuir esse estado com animações, atribuí-lo-emos a comportamentos e mais no Inspetor, você verá
que há um botão 'Adicionar comportamento'.
Selecione isso e criaremos um novo script. Vamos chamar de 'Patrulha' e 'Criar e adicionar'. Isso criará um arquivo
C # chamado Patrol na pasta Assets que agora está associado a esse estado de
Patrol e, se você clicar duas vezes e abrir, encontrará um monte de código
comentado que é acionado por esse estado. Qualquer estado em uma máquina de estado possui 3 processos que são executados em momentos diferentes.
Ele tem um Enter, uma Atualização e uma Saída. Enter é executado assim que o estado é transferido para.
O estado entra no loop infinito da atualização. A atualização continua em execução até que a transição para
fora do estado seja acionada. Nesse ponto, antes de
sair do estado, o método Exit é executado. De volta ao nosso script de comportamento da máquina de estado, encontraremos cada um desses métodos incluídos.
O primeiro é um
Enter (vamos tirar os comentários para isso).
O próximo é a atualização (remova os comentários para isso também)
e, por fim, há uma
saída (também vamos nos livrar desses comentários).
Os outros métodos ('OnStateMove' e 'OnStateIK') são usados pelo sistema de animação.
Não estamos fazendo animação neste caso, então vamos removê-los.
Agora criaremos um sistema realmente simples de 'seguimento de waypoints' neste código. No topo, vou
definir 3 valores como este.
Portanto, o primeiro é o 'NPC' e é para agarrar o NPC que está usando esse código por meio do Animator e chegaremos a isso
em um momento.
Em seguida, precisamos de uma matriz de todos os pontos de referência, para que possamos percorrer esses pontos
e mover o NPC e, então, precisamos manter o controle de qual ponto de referência estamos
indo atualmente, que será nesse int chamado currentWP.
Agora, para se apossar dos pontos de referência, porque esse
é um objeto com script, não há como o Inspetor enviar valores para isso e, portanto, precisamos obtê-los em tempo
de execução.
Podemos adicionar um método Awake (que eu vou fazer aqui em cima) a
isso e o que ele fará é definir pontos de referência para encontrar todos os GameObjects com a tag 'waypoint'.
Quando você tiver isso lá, se você simplesmente voltar para o Unity (eu vou salvá-lo) e dar uma
olhada nos waypoints que eu adicionei e você verá que eles estão marcados com 'waypoint' .
Então é assim que o script os encontrará. O OnStateEnter
será executado toda vez que esse estado for transferido, não importa
o que o NPC esteja fazendo. Então, você precisa considerar o que precisa aqui que irá configurar o NPC para
patrulhamento, neste caso.
Agora o que eu quero fazer é adicioná-los.
Primeiro de tudo, eu vou pegar o NPC (que é o nosso valor que definimos no topo).
Agora podemos fazer com que o NPC execute esse script usando o objeto animador que está sendo passado por aqui
e só estou configurando isso apenas para me poupar um pouco de digitação, tanto quanto precisar digitá-lo
toda vez que quiser obter o transformação ou posição do NPC.
Então, isso é apenas agarrar isso.
Agora, toda vez que entrarmos em Patrulha, vou dizer ao NPC que ele precisa ir para o ponto 0.
Portanto, se for interrompido em sua busca de patrulhamento (por ter que perseguir alguém), ele sempre voltará
e começará na posição 0 e contará novamente a partir daí.
Então esse é o OnStateEnter. O OnStateUpdate será executado repetidamente, enquanto o NPC estiver nesse
estado.
Então é aqui que vamos colocar o código para patrulhar e mover esses pontos de referência.
O que isso está fazendo é, antes de tudo, perguntar se há algum waypoint (por isso, se a
matriz do waypoint tiver 0 de comprimento e depois 'retornar', porque não há sentido em se movimentar nos
waypoints inexistentes).
Em seguida, ele faz um cálculo de distância e esse cálculo de distância funciona onde o NPC está em relação
ao waypoint atual para o qual está se dirigindo. Se ele alcançou o waypoint atual com precisão neste caso, de 3,
ele obterá um novo waypoint e atualizará o waypoint em 1. Começa em 0, então agora vai
subir para 1.
Em seguida, ele perguntará se o waypoint é maior ou igual ao comprimento da matriz e definirá
o waypoint atual de volta a 0.
Portanto, isso fará um ciclo (ou contará até o final e depois retornará) e criará um circuito de pontos
de referência.
Depois disso, há um código que moverá o tanque para a frente e o fará ficar na direção do
waypoint para o qual ele está viajando.
Primeiro, calculamos a direção na qual queremos que o tanque viaje e, em seguida, usando essa direção,
aplicamos um slerp.
Então Quaternion. Slerp vai virar lentamente o NPC em direção ao waypoint.
Agora você pode modificar a rapidez com que essa rotação acontece com esse quantificador aqui.
Portanto, no momento, a velocidade da rotação está definida como 1.
Depois disso, fazemos um Translate e empurramos o NPC ao longo do eixo z (que é o eixo voltado para a frente).
Portanto, a rotação está fazendo todo o trabalho, na medida em que se orienta com o waypoint e este Translate está
apenas empurrando-o para a frente
e a velocidade, neste caso, para nossa direção para a frente é um valor 2 e é aí que você pode alterá-lo
se quiser quer se mover mais rápido. Para OnStateExit, não há
nada de que precisamos neste momento; portanto, vamos deixar isso em branco.
Então agora vamos salvar nossa Patrulha e voltaremos à Unidade. O que faremos agora é no nosso tanque verde, vamos
adicionar essa animação (que é a nossa máquina de estados finitos em vez de uma animação,
mas o processo é o mesmo). Então, vamos adicionar um componente ... adicionaremos um Animator e,
em seguida, na parte Controller do Animator, queremos
arrastar e soltar nosso NPCFSM que acabamos de criar. Obviamente, não há movimento de avatar ou raiz a ser aplicado,
porque estamos apenas usando o sistema de comportamento dentro desta máquina de estado finito para conduzir o movimento de nosso tanque.
Agora, com tudo isso configurado, podemos pressionar Play.
Você pode ver esse comportamento funcionando na janela do Animator, se você selecionar o estado atual em
andamento.
Se você não conseguir ver isso, selecione o tanque na Hierarquia também.
O que isso está mostrando é que o método Update está sendo executado repetidamente.
Agora não há transições fora daqui para fazer com que mais alguma coisa aconteça, exceto que esse pequeno
tanque verde apenas contornará os pontos de referência na ordem em que eles terminam nesse conjunto de pontos de referência.
No próximo tutorial, começaremos a adicionar mais estados à nossa Máquina de estados finitos para que o tanque
possa começar a atirar e perseguir o jogador.