Quase todo jogo requer inteligência artificial (IA) que interaja com o usuário, na maioria das vezes na forma de uma força hostil ao jogador. Em alguns casos, a IA deve ajudar o jogador, em outros deve combatê-la, mas todos os personagens controlados pelo computador têm algumas semelhanças. Dependendo dos requisitos do projeto, a IA pode usar comportamentos simples ou complexos. Tais requisitos podem ser diplomacia com outro jogador ou um simples passeio pela plataforma. Seja como for, é necessário garantir que a IA faça seu trabalho com eficiência.
Neste projeto, demonstrarei uma inteligência artificial muito simples. Suponha que criamos um jogo no qual um jogador deve se aproximar do quartel-general inimigo. Quando um jogador é notado por uma câmera de segurança, inimigos são criados nas proximidades e, por um curto período de tempo, perseguem o jogador. É isso que estamos implementando no projeto no nível mais simples. Após a conclusão do projeto, você receberá o objeto de um jogador controlado, um círculo usado como câmera de um inimigo e um objeto de inimigo que perseguirá o jogador quando o objeto da câmera informar sobre sua presença.
Preparação
Primeiro, precisamos criar um projeto 3D. Clique no botão
Novo na parte superior da janela após iniciar o Unity, como mostra a Figura 1.
Figura 1: criando um novo projetoNomeie seu projeto de
IA e verifique se é um projeto 3D. Após escolher um local no computador para armazenar o projeto, clique no botão
Criar Projeto na parte inferior, mostrado na Figura 2.
Figura 2: tela de configuração do projetoDepois de criar o projeto, a primeira coisa que precisamos fazer é configurar as pastas na janela
Assets para organizar nosso trabalho. Clique com o botão direito na janela
Ativos e selecione
Criar → Pasta para criar uma nova pasta. Nomeie essa pasta de
Materiais . Em seguida, crie uma segunda pasta e nomeie-a como
Scripts . A Figura 3 mostra como deve ser.
Figura 3: criando uma nova pastaDepois de tudo isso, a janela
Assets deve se parecer com a mostrada na Figura 4.
Figura 4: Janela Ativos .Em seguida, crie um piso no qual todos os objetos permaneçam. Na janela
Hierarquia , selecione
Criar → Objeto 3D → Plano para criar um objeto plano que será usado como piso.
Figura 5: Criando um objeto plano.Nomeie esse objeto
Floor e altere seu valor
X Scale para 7 e o valor
Z Scale para 3. Depois disso, a janela
Inspector com o objeto
Floor selecionado deve se parecer com o mostrado na Figura 6.
Figura 6: Definindo as propriedades do objeto Floor .Agora, precisamos criar um novo material para o
Floor para diferenciá-lo dos demais objetos que serão colocados na cena. Na pasta
Materiais da janela
Ativos , crie um novo material clicando com o botão direito do mouse na janela
Ativos e escolhendo
Criar → Material .
Figura 7: criando novo materialQuando terminar, nomeie o material como
Piso .
Figura 8: Material do piso .Na parte superior da janela do
Inspetor com
Piso selecionado, selecione um seletor de cores.
Figura 9: escolhendo um seletor de cores.
Obviamente, você pode escolher qualquer cor para o piso, mas neste exemplo eu escolhi o marrom vermelho, como mostra a Figura 10.
Figura 10: seletor de cores.
Selecione o objeto
Piso na janela
Hierarquia e, no componente
Renderizador de malha , selecione a pequena seta ao lado de
Materiais .
Figura 11: Preparando para uma mudança de material.Arraste o material
Piso da janela
Ativos para o campo
Elemento 0 do componente
Renderizador de malha na janela
Inspetor .
Figura 12: Definindo o material do piso como o material do objeto Piso .Depois de terminar com o objeto
Floor , precisamos criar em torno da área da parede para que o jogador não possa cair da borda. Volte para
Criar → Objeto 3D → Plano para criar um novo plano. Chamamos esse plano de
parede e o definimos nas mesmas dimensões que
Floor , ou seja,
X Scale com um valor de 7 e
Z Scale com um valor de 3. Em seguida, crie mais três paredes, selecione um objeto e pressione Ctrl + D três vezes. sexo de acordo com os dados da tabela.
Título
| Posição X
| Posição Y
| Posição z
| Rotação x
| Rotação z
|
Parede
| -35
| 21
| 0 0
| 0 0
| -90
|
Parede (1) | -1
| 11
| -15
| 90
| 0 0
|
Parede (2)
| -1
| 11
| 13,5
| -90
| 0 0
|
Parede (3)
| 34
| 21
| 0 0
| 0 0
| 90 |
Tabela 1: Posições e rotações de todos os objetos da
parede .
Depois de concluir tudo isso, você precisa alterar a posição da câmera para que ela olhe para o chão de cima. Selecione o objeto
Câmera principal e defina a
posição Y para 30, a
posição Z para 0 e a
rotação X para 80.
Figura 13: configurando o objeto da câmera.A cena está preparada, então é hora de criar o personagem do jogador. Na janela
Hierarquia , clique em
Criar → Objeto 3D → Esfera para criar um objeto de esfera. Nomeie esse objeto como
Player e clique no botão
Adicionar componente na parte inferior da janela do
Inspetor .
Figura 14: adicionando um novo componente.Agora encontre o
corpo rígido . Depois disso, selecione o componente
Rigidbody na lista e adicione o
Rigidbody ao objeto
Player .
Figura 15: adicionando um componente Rigidbody .Em seguida, você precisa atribuir uma tag ao jogador, que mais tarde será útil para nós no código. Clique no menu suspenso
Tag , no canto superior esquerdo da janela
Inspetor , e selecione a tag
Player .
Figura 16: Definindo uma nova tag.Precisamos definir a posição do jogador para que ele não fique embaixo do objeto
Floor . No exemplo, coloquei o player no canto superior esquerdo com a
posição X igual a 26, a
posição Y igual a 1 e a
posição Z igual a -9.
Figura 17: posicionamento do jogador.Para que nosso código futuro funcione corretamente, é claro que precisamos anexá-lo ao objeto. Volte para a janela
Hierarquia e desta vez selecione
Criar → Objeto 3D → Cubo . Chame esse cubo
Guard , adicione o componente
Rigidbody e o componente
NavMesh Agent usando o botão
Add Component na janela
Inspector . Em seguida, coloque-o em algum lugar no canto superior esquerdo da cena. Depois disso, a janela
Inspetor do objeto
Guard ficará assim:
Figura 18: Objeto de guarda na janela Inspetor .E este objeto deve estar localizado assim:
Figura 19: Colocação do objeto Guard .Finalmente, precisamos de um objeto usado como o "olho" do objeto
Guarda , que notificará o
Guarda que o jogador está tocando nele. Pela última vez, vá para a janela
Hierarquia e selecione
Criar → Objeto 3D → Esfera para criar outro objeto de esfera. Nomeie esse objeto
Looker . Desta vez, não precisamos adicionar outros componentes a ele. No entanto, redimensionaremos o objeto. Depois de escolher o
Looker , altere as seguintes variáveis do componente
Transform na janela
Inspector .
- Escala X em 9.
- Escala Y a 0,5.
- Escala Z em 9.
Depois disso, posicione o
Looker de forma que ele esteja localizado na parte superior central do piso, como mostra a Figura 20.
Figura 20: Localização do Looker.É o momento certo para fornecer ao
Looker um material exclusivo, para que você possa ver que vale a pena evitar. Na pasta
Materiais da janela
Ativos , clique com o botão direito do mouse e crie um novo material. Nomeie-o
Looker e dê uma cor vermelha brilhante. Depois disso, designe esse material como o material do objeto
Looker para alterar sua cor. Depois disso, a cena deve ficar assim:
Figura 21: Objeto visualizador com novo material.A única coisa que resta para nós é criar uma malha de navegação para o
Guard , na qual ele pode se mover. Há um menu
Janela na parte superior do editor do Unity. Escolha
Janela → Navegação para abrir a janela
Navegação mostrada na Figura 22.
Figura 22: Janela de navegação .Selecione o objeto
Piso na
Hierarquia e, na janela
Navegação , marque a caixa de seleção
Estática da
Navegação .
Figura 23: Estática de navegação .Em seguida, selecione a opção
Assar na parte superior da janela.
Figura 24: Alterne para o menu Bake .O menu
Bake é aberto, no qual você pode alterar as propriedades da malha de navegação que vamos criar. No nosso exemplo, nada precisa ser alterado. Basta clicar no botão
Bake no canto inferior direito.
Figura 25: criando uma nova malha de navegação.Nesse ponto, o Unity solicitará que você salve a cena. Salve-o, após o qual uma malha de navegação será criada. Agora a cena ficará assim:
Figura 26: A cena atual com a malha de navegação adicionada.Agora tudo no Unity está configurado, então é hora de criar os scripts necessários para o projeto funcionar. Na janela
Ativos , clique com o botão direito do mouse e selecione
Criar → Script C # . Nomeie esse script como
Player . Repita esta operação mais duas vezes, criando scripts com os nomes
Guard e
Looker .
Figura 27: criando um novo script.Depois disso, a pasta
Scripts na janela
Assets ficará assim:
Figura 28: Pasta Scripts .Primeiro, começaremos a escrever o código de script do
Player . Clique duas vezes no script
Player na janela
Assets para abrir o Visual Studio e começar a criar o código.
Código
O script
Player é bastante simples, basta permitir que o usuário mova o objeto bola. Sob a declaração de classe, precisamos obter um link para o componente
Rigidbody que criamos anteriormente no projeto.
private Rigidbody rb;
Logo depois, na função
Start , comandamos o Unity para definir o atual componente
Rigidbody do objeto
Player como
rb .
rb = GetComponent<Rigidbody>();
Depois disso, o script
Player ficará assim:
Figura 29: Script do jogador no momento.Agora que o valor
rb está atribuído, precisamos permitir que o objeto
Player se mova quando pressionamos as teclas de seta. Para mover o objeto, usaremos a física, aplicando força ao objeto quando o usuário pressionar as teclas de seta. Para fazer isso, basta adicionar o seguinte código à função
Atualizar :
if (Input.GetKey(KeyCode.UpArrow)) rb.AddForce(Vector3.forward * 20); if (Input.GetKey(KeyCode.DownArrow)) rb.AddForce(Vector3.back * 20); if (Input.GetKey(KeyCode.LeftArrow)) rb.AddForce(Vector3.left * 20); if (Input.GetKey(KeyCode.RightArrow)) rb.AddForce(Vector3.right * 20);
Com isso, concluímos o script do
Player . O script final terá a seguinte aparência:
Figura 30: o script Player concluído.Salve seu trabalho e retorne ao Unity. Desta vez, selecione o script
Guard na janela
Assets . Para fazer o código do
Guard funcionar, você precisa adicionar a construção using na parte superior do script.
using UnityEngine.AI;
Em seguida, declare as seguintes variáveis imediatamente após a declaração da classe.
public GameObject player; private NavMeshAgent navmesh;
O objeto
Player é usado como o valor da variável
player do objeto
Guard . Isso será útil mais tarde, quando comandarmos o objeto
Guarda para perseguir o jogador. Em seguida, a variável
navmesh é
declarada para receber o componente
NavMeshAgent do objeto. Nós o usaremos mais tarde quando o
Guarda começar a perseguir o jogador depois que ele descobrir que o jogador está tocando o objeto
Looker . Na função
Start , precisamos definir o valor da variável
navmesh para o componente
NavMesh Agent do objeto:
navmesh = GetComponent<NavMeshAgent>();
Em seguida, na função
Atualizar , adicionamos uma única linha de código:
navmesh.destination = player.transform.position;
Esta linha define o destino para o objeto
Guard . No nosso caso, ele assumirá a posição atual do objeto
Player e se moverá para este ponto. Após a operação, o objeto perseguirá constantemente o jogador. A questão é: como é realizado o processo de resposta? Não será codificado no script
Guard , mas no script
Looker . Antes de passar para o script Looker, observe a Figura 31 para verificar seu código de script do
Guard .
Figura 31: o script Guard concluído.Dentro do
Looker, novamente precisamos declarar as seguintes variáveis:
public GameObject guard; private float reset = 5; private bool movingDown;
Depois disso, comentamos a função
Iniciar , da qual não precisamos neste script. Vamos para a função
Update e adicione o seguinte código:
if (movingDown == false) transform.position -= new Vector3(0, 0, 0.1f); else transform.position += new Vector3(0, 0, 0.1f); if (transform.position.z > 10) movingDown = false; else if (transform.position.z < -10) movingDown = true; reset -= Time.deltaTime; if (reset < 0) { guard.GetComponent<Guard>().enabled = false; GetComponent<SphereCollider>().enabled = true; }
É aqui que as principais ações do projeto ocorrem, então vamos analisar o código. Primeiramente, dependendo do valor da variável booleana
movingDown , o objeto ao qual esse script está anexado será movido para cima ou para baixo. Assim que ele chegar a um certo ponto, ele mudará de direção. Em seguida, o
Looker reduzirá o valor de redefinição com base em tempo real. Assim que o cronômetro se tornar menor que zero, ele pegará o script
Guard do objeto
Guard e o desativará. Depois disso, o objeto
Guard começará a se mover para a última posição conhecida do jogador até então e depois parará.
O Looker também liga novamente o colisor para que todo o processo possa começar de novo. Agora, nosso script fica assim:
Figura 32: Script do visualizador .Falando em coletores: é hora de criar um código de conflito que redefina o timer do
Looker e inclua o script
Guard . Na função
Atualizar , crie o seguinte código:
private void OnCollisionEnter(Collision collision) { if (collision.gameObject.tag == "Player") { guard.GetComponent<Guard>().enabled = true; reset = 5; GetComponent<SphereCollider>().enabled = false; } }
O OnCollisionEnter Unity o reconhece automaticamente como um código de colisão e, portanto, o executa quando ocorre uma colisão com outro objeto. No nosso caso, ele primeiro verifica se o objeto em colisão possui uma tag
Player . Caso contrário, ele ignora o restante do código. Caso contrário, ele ativa o script
Guard , define o timer de
redefinição para 5 (ou seja, cinco segundos) e desativa o colisor para que o jogador ainda possa se mover pelo objeto e não ficar preso acidentalmente no objeto
Looker . A função é mostrada na Figura 33.
Figura 33: Código de colisão para o Looker.
É tudo o que o código do projeto está pronto! Você pode fazer mais algumas coisas antes de terminar o projeto. Salve todo o trabalho e retorne ao Unity.
Conclusão do projeto
Para concluir o projeto, basta anexar scripts aos objetos correspondentes e definir várias variáveis. Primeiro, vá da janela
Navegação para a janela
Inspetor :
Figura 34: transição para a janela Inspetor.
Depois disso, vamos começar com o objeto
Player . Selecione-o na janela
Hierarquia e, na parte inferior da janela
Inspetor , clique no botão
Adicionar componente e adicione o script
Player . Isso completa o objeto
Player .
Figura 35: Componente de script do Player.
Em seguida, selecione o objeto
Guard . Como antes, anexe o script
Guard ao objeto. Desta vez, precisamos dizer ao
guarda quem é o jogador. Para fazer isso, arraste o objeto
Player da
Hierarquia para o campo
Player do componente de script
Guard , como mostra a Figura 36.
Figura 36: Fazendo com que o Player objete o valor do campo Player .Também precisamos desativar o script
Guard . Em nosso projeto,
Guard perseguirá o jogador depois de ativar seu script. Esse script de
guarda deve ser incluído somente depois que o jogador tocar no objeto
Looker . Tudo que você precisa fazer é desmarcar a caixa ao lado do texto
Guard (Script) no componente:
Figura 37: Desativando o script Guard .Por fim, vamos para o objeto
Looker e anexamos o script
Looker . Dessa vez, o objeto
Looker precisará de um objeto
Guard como o valor de sua variável
Guard . Assim como atribuímos o objeto
Player à variável
Player do script
Guard , faremos o mesmo com o objeto
Guard e o script
Looker . Arraste o
Guard da
Hierarquia para o campo
Guard do script
Looker . E o projeto está concluído! Clique no botão Play na parte superior do editor do Unity para testar seu projeto.
Figura 38: Testando um projeto.Tente mover o objeto
Player para o objeto
Looker (lembre-se de que o movimento é feito com setas!). Observe que, depois disso, o objeto
Guard começará a perseguir o jogador. Ele continuará a busca por cerca de 5 segundos, após o que desistirá.
Figura 39: Um projeto totalmente concluído em ação.Conclusão
Essa IA é muito simples, mas pode ser facilmente expandida. Suponha que, se imaginarmos que o objeto
Looker é uma câmera, e o guarda o olhar para encontrá-lo, será lógico atribuir ao objeto o seu próprio par de olhos. O jogador pode se aproximar das câmeras, mas deve levar em conta os olhos do guarda. Você também pode combinar este projeto com o
conceito de encontrar o caminho : dê ao guarda o caminho que ele seguirá, criando um ambiente mais interessante para o jogador.
Uma IA tão simples pode ser desenvolvida de várias maneiras diferentes. Você pode não querer fazer nada do que precede e decidir fazer algo de sua preferência. Eu aconselho você a experimentar, talvez você tenha a idéia de um projeto interessante, que vale a pena levar ao fim.