Combate em Godot! | Thomas Yanuziello | Skillshare
Pesquisar

Velocidade de reprodução


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Assista a este curso e milhares de outros

Tenha acesso ilimitado a todos os cursos
Oferecidos por líderes do setor e profissionais do mercado
Os temas incluem ilustração, design, fotografia e muito mais

Aulas neste curso

    • 1.

      Introdução

      1:44

    • 2.

      Configuração

      0:32

    • 3.

      Lock On

      15:52

    • 4.

      Strafe

      13:47

    • 5.

      Ataque

      20:46

    • 6.

      Arma

      17:20

    • 7.

      Hit

      15:43

    • 8.

      Dodge

      14:43

    • 9.

      Bloqueio

      15:12

    • 10.

      Fotografe

      17:43

    • 11.

      Inimigo

      15:41

  • --
  • Nível iniciante
  • Nível intermediário
  • Nível avançado
  • Todos os níveis

Gerado pela comunidade

O nível é determinado pela opinião da maioria dos estudantes que avaliaram este curso. Mostramos a recomendação do professor até que sejam coletadas as respostas de pelo menos 5 estudantes.

22

Estudantes

--

Projeto

Sobre este curso

Este curso é uma continuação do inventário e lojas em Godot!

Clique no link do meu site em meu perfil para participar do nosso servidor de discord.

Neste curso, vamos abordar o bloqueio a um alvo, locomoção, ataque, ser atingido, esquivar, bloqueio, disparo de projéteis e IA básica do inimigo.

Você também vai aprender habilidades úteis para trabalhar com o motor de jogo Godot, organizar e projetar seus projetos para serem mais escaláveis.  Você vai aprender como codificar com GDscript, com tudo explicado em detalhes.  Nossos scripts serão escritos para serem altamente personalizáveis e reutilizáveis.  Todos os arquivos do projeto também estarão disponíveis no GitHub se você precisar revisar o projeto como estava depois de concluir cada aula.  Esses vídeos foram gravados usando a versão Godot 4.3.

Este curso vai fazer parte de uma série projetada para ensinar pedaços de desenvolvimento de jogos do tamanho de uma mordida que podem ser usados ​​de forma intercambiável uns com os outros.  Então, deixe-me saber quais tipos de jogos você é interessante em aprender como fazer e vou tentar incluí-los em futuros cursos desta série.

Conheça seu professor

Teacher Profile Image

Thomas Yanuziello

Indie Game Developer

Professor
Level: All Levels

Nota do curso

As expectativas foram atingidas?
    Superou!
  • 0%
  • Sim
  • 0%
  • Um pouco
  • 0%
  • Não
  • 0%

Por que fazer parte da Skillshare?

Faça cursos premiados Skillshare Original

Cada curso possui aulas curtas e projetos práticos

Sua assinatura apoia os professores da Skillshare

Aprenda em qualquer lugar

Faça cursos em qualquer lugar com o aplicativo da Skillshare. Assista no avião, no metrô ou em qualquer lugar que funcione melhor para você, por streaming ou download.

Transcrições

1. Introdução: Os jogos de combate e videogames podem parecer assustadores e difíceis de implementar Este curso fornecerá todas as ferramentas e conhecimentos necessários para criar um sistema de combate escalável e dinâmico em Gado. Vamos dividir o sistema de combate em mecânicas individuais e combiná-las para criar um sistema de combate de ação robusto que pode ser personalizado para atender às suas necessidades Você aprenderá a combinar animações de combate e movimento Sincronize caixas de sucesso com animações de ataque, implemente molduras oculares em animações de esquiva e bloqueie inimigos bloqueie Dispare projéteis com uma arma arranjada e controle os inimigos com scripts de IA Se precisar de ajuda, nosso servidor de discórdia está cheio de outros estudantes e desenvolvedores de jogos que podem responder a quaisquer perguntas que você possa ter Clique no link do site em meu perfil para participar. Vou usar um projeto inicial feito em Deus, versão 4.3 que está disponível no meu GitHub usando ativos gratuitos do dot IO Mas você pode acompanhar seu próprio projeto usando ativos diferentes. Para tirar o máximo proveito desse curso, você precisará de uma cena em seu projeto com um personagem que o jogador possa controlar e pelo menos um inimigo. Você também pode querer ter um sistema de inventário e equipamento capaz de equipar personagens com uma arma e um escudo Para obter mais informações sobre esses tópicos, consulte meu curso anterior. O combate não precisa ser uma batalha difícil. Vamos sacar nossas armas e enfrentar o combate juntos. 2. Configuração: Olá, amigos. Antes de começarmos, você deve ter um projeto com um personagem de jogador que possa se mover em um ambiente e alguns inimigos para ele lutar. Você também pode querer ter um menu de inventário capaz de equipar itens, incluindo pelo menos uma arma mala, uma arma arranjada e um escudo Ao longo deste curso, adicionaremos controles, mecânicas e animações ao nosso projeto para fixar um alvo, atacar, esquivar, bloquear e disparar projéteis atacar, esquivar, bloquear 3. Lock On: Em nossa primeira aula, permitiremos que o jogador bloqueie um inimigo. Vamos começar adicionando um mapeamento de entrada para ativar o bloqueio Abrindo as configurações do projeto, alternando para a guia do mapa de entrada. Podemos adicionar um evento de entrada chamado Toggle Lock. Ao rolar para baixo para encontrar o novo evento de entrada, vincularei a tecla Q no teclado e o botão direito do meu controle a esse No script de manipulação de entradas do jogador, precisaremos de referências ao personagem, braço de mola e à câmera, tudo configurado usando addon ready. Durante a função de entrada, após verificar a pausa, abra ou feche o menu de inventário e se o controle do jogador foi desativado Eu dividi o resto da entrada em câmera e controles de personagens para uma melhor organização. Atualmente, o único controle da câmera é girar o braço de mola segura a câmera usando o mouse Vamos também verificar se o botão de bloqueio foi pressionado. Essa será uma entrada sensível ao contexto com várias funções possíveis diferentes. Precisaremos saber se o jogador está atualmente preso a um alvo. Então, vamos declarar uma variável para manter o alvo atualmente bloqueado como um nó três D, para que qualquer objeto de três D em nosso mundo de jogo possa ser bloqueado Podemos primeiro dividir as funções do botão de bloqueio de alternância em duas categorias possíveis, se o valor do alvo for nulo ou não, que podemos encurtar para Vamos começar no bloco s, onde o jogador não está preso a nada no momento. Aqui, precisaremos atribuir o valor do alvo como o alvo visível mais e podemos delegar a responsabilidade de descobrir qual é o alvo visível mais próximo da câmera No caso de não haver um alvo visível mais próximo, o alvo ainda será nulo Em muitos jogos de ação e aventura, ao pressionar o botão de bloqueio do togo, não há nada para bloquear. A câmera então reinicia para ficar atrás do personagem do jogador, que será uma função do braço de mola Se o jogador já estiver preso em um alvo e pressionar o botão de bloqueio do togo, também há vários casos a serem considerados Se houver vários alvos visíveis, o jogador se fixará no próximo alvo visível mais próximo, além daquele em que está bloqueado no momento Podemos reutilizar a mesma função da câmera para encontrar o alvo mais próximo Mas desta vez também forneça o alvo atual como argumento, e escreveremos o algoritmo para ignorar esse alvo. No caso abaixo, ainda podemos passar o alvo atual, pois seu valor é nulo, então não teremos nada a ignorar Se não houver vários alvos visíveis, essa função também retornará null e o bloqueio será desativado Independentemente de haver ou não vários alvos, se o jogador também estiver pressionando, maioria dos jogos desativará o bloqueio nesse Podemos determinar se a direção de entrada fornecida é semelhante à direção descendente usando um produto escalar dos dois vetores e verificando se é maior que 0,75 Isso cobrirá todas as direções próximas à descida, mas não alcançando as diagonais Queremos ter a capacidade de ativar o bloqueio de fora do script, então seria uma boa ideia torná-lo uma função pública Vamos chamá-lo de toggle lock e fornecer um parâmetro opcional para forçar o bloqueio com um valor padrão false O valor do alvo será definido como nulo se estiver sendo forçado a sair. Caso contrário, ele pode ser configurado para o alvo visível mais próximo, conforme determinado pela câmera, ignorando o alvo atual, se houver um Todos os três casos acima agora podem chamar o Toggle lock , bastando especificar que o bloqueio está sendo forçado a ser desativado no caso de a direção de entrada para baixo também ser fornecida, e outros scripts também podem forçar o player a bloquear ou desligar por Mudando para o script spring arm. Vamos supor que o jogador pressione o botão de bloqueio, mas nenhum alvo Queremos que o braço de mola posicione a câmera atrás do personagem. Portanto, precisaremos de uma referência ao caractere ao qual o braço da mola está conectado, que no meu caso sempre será o nó principal do braço da mola. Se você estiver usando uma estrutura de nós diferente, talvez queira exportar essa variável e definir seu valor no painel do inspetor Para girar a câmera atrás personagem gradualmente ao longo do tempo, usaremos uma variável de interpolação do tipo interpolação Seria uma boa ideia exportar uma variável durante a interpolação Vou usar um quarto de segundo. Também podemos querer um valor para a rotação x preferida para redefinir a rotação dois dos braços de mola. Vou usar 0,5 radianos negativos, posicionando a câmera um pouco acima do personagem, olhando para frente e ligeiramente para baixo em um ângulo Vamos também declarar uma variável para manter a rotação alvo das interpolações como um vetor três e inicializá-la como um vetor três com a rotação x redefinida como seu valor x, mas zero para as rotações y e Dando uma definição à função, também podemos aceitar um parâmetro opcional para a duração da interpolação usando isso como seu valor padrão para que possa ser sobrescrito Para girar a câmera atrás do personagem, podemos chamar uma nova função privada interpolar a rotação dos braços da mola Especificando que queremos que a rotação y seja a rotação das plataformas de caracteres mais uma meia rotação representada como Pi Em seguida, vamos escrever a função privada que interpola a rotação dos braços da mola, aceitando uma rotação y alvo como flutuação, bem como uma duração para a interpolação com um valor padrão da Começaremos definindo a propriedade y da rotação do alvo como a rotação y do alvo aceita como parâmetro. Mas para garantir que a rotação sempre siga o caminho mais curto ao redor do caractere, devemos dividir seu valor para estar sempre entre o ponto de rotação atual y menos meia rotação e o ponto de rotação atual y mais meia Se uma interpolação já existe e está em execução , devemos eliminá-la antes de criar uma nova Podemos então intercalar a rotação dos braços da mola com a rotação do alvo ao longo da duração Em seguida, vamos deixar a câmera detectar alvos visíveis. Minha câmera ainda não tem nenhum comportamento programado, então vamos adicionar um novo script e colocá-lo na pasta de scripts dos jogadores Precisaremos de uma função pública para obter o alvo visível mais próximo, aceitando um parâmetro opcional do alvo atual com um valor padrão de null, para que possamos potencialmente ignorá-lo Isso retornará um nó três D, e o caso padrão será retornar null se não conseguirmos encontrar um alvo visível Para determinar qual dos alvos visíveis está mais próximo, precisaremos manter uma lista de todos os alvos visíveis. Vamos declarar outra variável para conter todos os alvos visíveis como uma matriz de nós três Ds. Inicializado para ficar vazio. Uma maneira fácil de saber quais alvos estão visíveis é conectar um nó D de área três à câmera. Vamos chamá-lo de alcance alvo. Essa área monitorará qualquer coisa na camada de colisão 11, que eu escolhi para representar inimigos Certifique-se de que seus inimigos tenham sua camada de colisão definida na mesma camada que está sendo mascarada pelo bloqueio na Também precisarei redefinir as áreas transformadas para posicioná-las na origem da câmera. O nó D da área três precisa de uma forma de colisão, e podemos preencher o recurso de forma com um polígono convexo Usando um polígono convexo, podemos definir a forma como uma pirâmide, que copia exatamente o campo de visão da câmera, mas com Como o campo de visão da câmera terá a forma de uma pirâmide de quatro lados, podemos defini-lo com cinco pontos sendo o primeiro ponto igual à posição da câmera Os outros quatro serão posicionados ao longo do eixo Z, a distância máxima do nosso alcance de bloqueio Vou usar uma distância máxima de 15 metros. Mudando para a visão ortogonal superior e ocultando o ambiente por um momento, ajustarei rapidamente as posições de cada ponto na pirâmide para corresponder aproximadamente ao campo de visão da câmera, 11,4 metros à esquerda e à direita Da mesma forma, na visão ortogonal esquerda, ajustando os valores y dos pontos da pirâmide, 6,4 Até termos uma forma de pirâmide, compatível com o campo de visão da câmera, que alcança 15 metros. Em seguida, voltarei à visão em perspectiva e voltarei a falar sobre a visibilidade do ambiente. Sempre que um corpo entra nessa área, conectando o sinal inserido pelo corpo ao script da câmera, podemos anexar o corpo à nossa matriz de alvos Da mesma forma, sempre que um corpo sai dessa área, o corpo pode ser apagado da matriz Qualquer corpo de colisão de três D na camada 11, que exista dentro dessa área agora será considerado um alvo visível No meu script spring arm, precisarei de qualquer tag para usar a função get parent. Executando o jogo e mudando para a árvore da cena remota, podemos selecionar a câmera e visualizar suas propriedades no inspetor, incluindo a matriz de alvos visíveis Conforme a câmera se move pela cena, a matriz de alvos visíveis é atualizada automaticamente para adicionar e remover cada inimigo à medida que eles entram ou saem do campo de visão. Pressionar o botão de bloqueio ainda não atingirá nada, mas podemos ver como ele reposiciona a câmera atrás do personagem Antes de permitir o bloqueio em um alvo, talvez também queiramos verificar se a linha de visão do jogador em relação ao alvo está obstruída pelo terreno Vamos também adicionar um nó de três D de projeção de raios à câmera e nomeá-lo como linha de visão. Em seguida, pegue uma referência a ela no script da câmera. Para encontrar o alvo visível mais próximo com nossa câmera, se a matriz estiver vazia, seu tamanho for zero, então não há alvos visíveis a serem considerados e devemos simplesmente retornar. Se houver alvos visíveis a serem considerados, precisaremos comparar as distâncias de cada um com a câmera para descobrir qual é o mais próximo. Para fazer isso, precisaremos de uma variável para manter a distância do alvo atual até a câmera flutuando A distância mais próxima à tona e o índice do alvo visível mais próximo como Definiremos a distância mais próxima como infinita usando a palavra-chave I NF e o índice mais próximo como menos um para significar que não é um Se depois de iterar por toda a matriz de alvos visíveis, o índice mais próximo ainda for negativo, nenhum alvo visível foi considerado válido e devemos retornar null Caso contrário, podemos retornar o alvo visível no índice mais próximo. Se o alvo visível no índice I for o alvo atual, podemos ignorá-lo com a declaração continuada Para qualquer outro alvo visível, precisaremos calcular sua distância da câmera. Podemos usar a distância ao quadrado pois é matematicamente mais eficiente Se a distância atual for menor que a distância mais próxima , precisaremos verificar se a linha de visão desse alvo está obstruída Primeiro, precisaremos redefinir qualquer rotação que a linha de visão tenha atualmente. Em seguida, defina a posição alvo do raio lançado para a posição global do alvo menos a posição global da câmera e force-a a atualizar Mas a posição dos personagens geralmente está no chão, que é facilmente obstruído por pequenos pedaços de terreno e nem sempre é um bom indicador da linha de visão Vamos também somar 1 metro de altura. Se a linha de visão está colidindo com algo e esse algo é o alvo visível, então a linha de visão não está obstruída por nada, que torna esse alvo o alvo visível mais próximo que encontramos Podemos definir a distância mais próxima da distância atual e o índice mais próximo I antes de prosseguir com o resto da matriz Agora, isso retornará o alvo visível nulo ou o alvo visível mais próximo da câmera A linha de visão também colidirá com a camada 11, procurando inimigos, mas também a camada um que seja obstruída pelo terreno Também seria bom informar ao jogador o que está bloqueado com o indicador de alvo. Vamos adicionar um nó Sprite de três D como filho do manipulador de entrada do player e renomeá-lo Para a textura, usarei o ponteiro em branco da barra de rolagem. Mas altere suas configurações de entrada para ativar o Alpha pré-multiplicado para que pareça um E reduza para um quarto de seu tamanho. Em seguida, expandindo a seção da bandeira, configurarei a bandeira do outdoor para habilitar, que ela esteja sempre voltada para a câmera E a bandeira de teste sem profundidade sempre desenhará o sprite sobre todo resto, independentemente de sua posição no espaço de três D em relação à câmera O indicador de alvo pode ficar invisível por padrão, pois o jogador começa sem um alvo para indicar. Obtendo uma referência ao indicador de destino usando o complemento pronto Em seguida, precisaremos posicioná-lo sobre o alvo bloqueado. Então, depois de determinar em que o jogador está preso, se há um alvo. Uma maneira fácil de fazer com que o indicador de alvo siga o alvo é repará-lo nesse alvo. Podemos então movê-lo alguns metros para cima para posicioná-lo sobre a cabeça do alvo e definir sua propriedade visível como verdadeira. Se não houver um alvo para indicar, podemos reparar o indicador de volta para esse nó e definir sua propriedade de visibilidade de volta para quedas para ocultá-la. Vamos experimentar. Quando pressionamos o botão de bloqueio, o inimigo mais próximo é atingido e o indicador posicionado sobre a cabeça do alvo Pressionando o botão de bloqueio novamente, mudança é para o próximo inimigo mais próximo Manter pressionado e pressionado o botão de bloqueio força o bloqueio Se houver apenas um alvo visível qual já estamos presos, bloqueio também está desativado. Agora temos o jogador bloqueando inimigos em nosso jogo. Na próxima lição, mudaremos o comportamento da câmera e do personagem enquanto estiverem bloqueados. Te vejo na próxima aula. 4. Strafe: Olá, amigos. Na lição anterior, adicionamos um botão de bloqueio sensível ao contexto ao nosso jogo Nesta lição, mudaremos a forma como os nós do jogador se comportam enquanto se fixam em um alvo Começando no script do player, quando um alvo estiver bloqueado, vamos emitir um sinal para que qualquer outro script possa ouvir e reagir ao valor da mudança de alvo, especificando o que foi direcionado como parâmetro Usando um setter, podemos emitir o sinal sempre que o valor do alvo for alterado por qualquer Agora, todos os três personagens, o braço de mola e a câmera podem se conectar ao sinal, usando-o para definir suas próprias variáveis privadas para o alvo. Não importa qual seja o valor do alvo no script de manipulação de entrada do player, todos os outros nós também terão as mesmas informações, inclusive se estiverem definidas como nulas Escrever uma função simples para cada um que define uma variável de destino local todos possam acessá-la facilmente. Depois que nosso personagem estiver preso em um alvo, esperaríamos que ele ficasse voltado para o alvo em vez de na direção em que está se movendo. No meu roteiro, a rotação do personagem está sendo feita no processo físico, que faz com que o personagem fique voltado para a direção da entrada do movimento Vamos declarar uma nova variável na parte superior do script, quer ver a direção como três E substitua a direção de entrada direção desejada na chamada de função. Então, antes dessa chamada de função, podemos verificar se o personagem está preso a um alvo. Se eles estiverem presos a um alvo, a direção que eles desejarão enfrentar será em direção ao alvo, que podemos determinar facilmente subtraindo suas posições globais Se eles não estiverem bloqueados, eles desejarão ficar voltados para a direção da entrada de movimento, da mesma forma que estavam antes. Agora, o personagem enfrenta o alvo bloqueado, mas suas animações em movimento locais não parecem muito boas, pois elas se misturam apenas com base na rapidez com que o personagem está se movendo e não na Na máquina de estado da árvore de animação do personagem, eles estão no estado de salto ocioso porque não há piso na cena O estado de movimento loco é um espaço de mistura unidimensional, combina as animações de andar e correr em marcha lenta com base na velocidade de movimento do personagem Vamos remover esse estado e substituí-lo por outra máquina de estado. Reconectando as transições aos outros estados, começando com uma transição do início para a locomoção para torná-lo Eu habilitei a transição para o jump start com um peso cruzado de 0,3 segundos. E salte da terra para a troca de locomoção no final com um destino cruzado de 0,67 segundos Vou omitir temporariamente a transição da locomoção para a marcha lenta enquanto trabalho na máquina de estado de locomoção, para que o personagem permaneça no estado de locomoção e eu possa ver os resultados em locomoção e eu possa ver os na máquina de estado de locomoção, para que o personagem permaneça no estado de locomoção e eu possa ver os resultados em tempo real. Pressionar o botão play forçará o personagem a entrar no estado de locomoção e ele jogará porque está vazio Dentro do estado de locomoção, precisaremos ter dois conjuntos diferentes de animações de locomoção para quando o personagem estiver preso a um alvo e quando não estiver, e poder fazer a transição entre eles não estiver, e poder O padrão será o mesmo de antes, um espaço loiro unidimensional Digamos que não está bloqueado. Então, também podemos adicionar um espaço loiro bidimensional. Vamos nomear este bloqueado. Adicionar uma transição de inicial para não bloqueada torna essa a padrão. Podemos então fazer a transição entre não bloqueado para bloqueado se o valor do alvo não for nulo, o que podemos encurtar para apenas alvo e fazer um pequeno crossfade E volte para o alvo não bloqueado, se não estiver bloqueado, com o mesmo crossfade Dentro do espaço de mistura não bloqueado . Podemos recriá-lo exatamente como era antes, com um valor mínimo de zero misturando animações de marcha lenta, caminhada e corrida com base na velocidade de movimento do personagem Feito isso, use as migalhas de pão para subir um nível até a máquina de estado de locomoção e pressione o botão play na máquina estado bloqueada para forçar o personagem a entrar Dentro do espaço de mesclagem bloqueado , combinaremos as animações com base na direção em que o personagem está se movendo em relação à direção para frente, que é em direção ao alvo Vou configurar o ajuste da grade em incrementos de um para facilitar as coisas Se posicionarmos nossa visão para ficar atrás do personagem e imaginarmos que ele está preso em um alvo à sua frente , o eixo y representa a rapidez o personagem está se aproximando ou se afastando do alvo. O eixo x representa a rapidez com que o personagem está se movendo para a esquerda ou para a direita , contornando o alvo Vamos começar colocando a animação ociosa no meio. Para o eixo x, vamos querer colocar uma animação de metralhamento esquerdo no lado esquerdo e uma animação lado esquerdo e uma metralhamento direito no lado direito Para o eixo y, podemos colocar uma animação em execução na posição avançada, o que gerará triângulos no espaço de mesclagem mostrando como as diferentes animações serão mescladas E adicionando uma animação andando para trás na posição y negativa, também adicionaremos mais triângulos Se mudarmos a posição de mesclagem, podemos ver a aparência do personagem enquanto damos a entrada de movimento em qualquer direção. Dependendo dos ativos que você está usando, você também pode ter animações de movimento diagonal para adicionar a esse espaço de mesclagem Às vezes, essa prévia não simula com precisão como o personagem se comportará enquanto o jogo estiver rodando E você deve sempre testá-lo jogando o jogo para ter certeza de que fica bem no jogo. Mas antes de fazermos isso, vamos retornar ao nível raiz da máquina de estado e adicionar a transição da locomoção para o salto ocioso sob a condição de que o personagem não esteja no chão Eu costumava usar um tempo de cross fade de 0,3 segundos para essa transição Também precisamos atualizar a parte do nosso script, que define a posição de mesclagem do espaço de mesclagem, o que no script do meu personagem está acontecendo na física terrestre. Selecionando a árvore de animação, podemos copiar o caminho da propriedade da posição de mesclagem não bloqueada e atualizada na função set. Mas isso só precisa ser definido se o personagem não estiver preso a um alvo. Se eles estiverem bloqueados em um alvo, precisaremos definir a posição de mesclagem do espaço de mistura bloqueado. A posição de mesclagem bloqueada é um vetor dois com um x e um y, que precisaremos calcular. Então, vamos declarar uma variável para mantê-la chamada locked on blend Para evitar repetir os mesmos cálculos várias vezes, também declararei outra variável para armazenar a velocidade relativa do personagem, que será sua velocidade x z dividida pela velocidade dividida pela Depois de calcular esse valor, a posição de mesclagem do espaço de mesclagem não bloqueado pode ser definida para o comprimento desse vetor Se o personagem estiver preso a um alvo, podemos encontrar o valor x da posição de mistura usando o produto escalar do vetor de base global x da plataforma com sua velocidade relativa O produto escalar de dois vetores resulta em um número que representa o quão semelhantes ou diferentes eles são Então, estamos verificando se a velocidade relativa do personagem é semelhante a velocidade relativa do personagem é a um vetor apontando diretamente para a direita Dependendo de como seu personagem está configurado, qual direção é considerada para frente, talvez seja necessário multiplicar esse valor por menos um para revertê-lo A posição de mesclagem y também pode ser determinada usando o mesmo método, mas usando o vetor z direto do caractere. Em seguida, enquanto estiver bloqueada em um alvo, a câmera deve olhar para o alvo, não para o personagem do jogador. Na função de processo da câmera, ignorando o Delta, se houver um alvo, podemos dizer à câmera que olhe para o alvo e adicionar 1 metro para não olhar para os pés Ao definir o valor do alvo, se o alvo for definido como nulo, podemos redefinir a rotação da câmera podemos redefinir a rotação da câmera para voltar ao mesmo que seu nó pai, o braço de mola, definindo sua rotação para o vetor 30 Também podemos acionar a função de bloqueio se o alvo atual sair do nosso limite de alcance visível O éter é bloqueado ou mudança automática para um alvo mais próximo Então, vamos adicionar um sinal para quando o alvo atual sair do alcance e emiti-lo se o corpo que saiu da área for o Podemos então conectar esse sinal ao script de manipulação de entrada do player. Chamando a função de bloqueio de alternância. Dependendo se você deseja que o comportamento mude para o alvo mais próximo ou simplesmente se bloqueie, talvez queira vincular um argumento verdadeiro para a força do parâmetro No script Spring Arm, enquanto estiver preso a um alvo, queremos que o braço de mola sempre aponte para longe do alvo para manter o alvo e o personagem do jogador à vista da câmera. Vamos adicionar uma nova variável para manter essa direção como um vetor três. Então, quando o valor do alvo está sendo definido, se não for nulo, podemos definir o valor da direção do alvo como a diferença em nossa posição global menos a posição global do alvo Isso resultará em um vetor apontando do alvo de volta para o personagem do jogador. Podemos então reutilizar a função de rotação de interpolação, mas ela espera um parâmetro flutuante representando uma Podemos obter a rotação y, que apontará nessa direção usando a função trigonométrica A t dois, fornecendo os valores x e z da nossa Depois que o alvo for definido, o braço de mola girará a câmera para ficar na direção oposta ao alvo atrás do jogador. Mas queremos que fique lá. Na função de processo, se o valor do alvo tiver sido definido e entre parênteses, se a interpolação não existir ou não estiver em execução, o que significa que a interpolação terminou e o braço da mola está em posição, podemos realizar os mesmos cálculos , mas apenas definir o valor da rotação y diretamente em vez de fazer outra significa que a interpolação terminou e o braço da mola está em posição, podemos realizar os mesmos cálculos , mas apenas definir o valor da rotação y diretamente em vez de y diretamente em vez Isso manterá o braço de mola apontando para longe do alvo, enquanto estiver preso ao alvo, mantendo o alvo e o personagem do jogador à vista da câmera. Por fim, no script de manipulação de entrada do jogador, queremos evitar que o jogador gire o braço da mola enquanto está preso em um alvo Isso está acontecendo em dois lugares diferentes no meu script, um para controles de PC usando o mouse e outro para suporte de controle com o controle direito. Então, vou apenas incluir ambos em uma instrução if para não permitir essas entradas enquanto estão bloqueados em um alvo. Vamos experimentá-lo. Quando bloqueamos um inimigo, a câmera foca no alvo, enquanto o braço da mola gira para posicionar a câmera na direção oposta Movendo o personagem, eles giram para enfrentar o inimigo e animar movimentos fluidos em todas as direções O braço de mola mantém a posição da câmera de estar atrás do personagem, apontando para longe do alvo, enquanto a câmera continua olhando para o alvo. Os controles normais da câmera do jogador foram desativados enquanto estavam bloqueados. Se o alvo bloqueado estiver fora do alcance, ele mudará automaticamente para o alvo mais próximo ou será bloqueado se não houver um em quem se fixar. Se forçarmos o bloqueio, a câmera se concentra novamente no personagem do jogador, o controle normal do braço de mola é retomado e as animações de locomoção do personagem animações Agora temos nossos nós de jogadores adaptando seus comportamentos para ficarem presos em um alvo Na próxima lição, faremos com que o personagem do jogador realize ataques. Te vejo na próxima aula. 5. Ataque: Olá, amigos. Na lição anterior, mudamos o comportamento dos nós do jogador enquanto estavam presos a um alvo. Nesta lição, adicionaremos animações de ataque para que os personagens possam atacar uns aos outros Vamos começar abrindo as configurações do projeto, a guia do mapa de entrada e adicionando um novo evento de entrada para atacar Vou usar o botão esquerdo do mouse e o botão direito do ombro no meu controle. Em seguida, no script do manipulador de entrada do jogador, podemos verificar se o botão de ataque foi pressionado ao verificar as entradas de controle do personagem Se o botão de ataque foi pressionado nesse quadro, devemos mandar o personagem atacar. Mas e se o personagem estiver ocupado? Eles podem estar pulando ou realizando alguma outra ação e talvez não queiramos que eles consigam atacar neste momento Exigir que o jogador espere até que o ataque seja possível antes de pressionar o botão seria bastante frustrante A maioria dos jogos modernos considera que o pressionamento do botão é válido por um curto período após o pressionamento do botão, que é conhecido como buffer de entrada Vamos adicionar uma hora ou um nó ao manipulador de entrada do player. Nomeie seu buffer de entrada e defina sua propriedade one shot como true, para que ele faça a contagem regressiva apenas uma vez por vez Obtendo uma referência a esse cronômetro de buffer de entrada usando addon ready, podemos iniciar o cronômetro depois de mandar o personagem atacar e aguardar o esse cronômetro de buffer de entrada usando addon ready, podemos iniciar o cronômetro depois de mandar o personagem atacar e aguardar o sinal de tempo limite. Depois que o cronômetro tiver contado até zero, diremos ao personagem que cancele a instrução dada para atacar Então, a qualquer momento enquanto o cronômetro estiver em contagem regressiva, o personagem tentará atacar quando estiver pronto O tempo de espera padrão para o cronômetro é de 1 segundo, o que é um tempo razoável para o buffer de entrada de ataque Outra entrada que talvez queiramos armazenar em buffer é a entrada de salto. Seguindo o mesmo padrão da entrada de ataque, podemos iniciar o cronômetro, aguardar o sinal de tempo limite cancelar a entrada de salto No script do personagem, vamos começar criando uma nova região de código para combate. Em seguida, mova a função alvo do jogador para essa região. Precisaremos de uma função pública para mandar o personagem atacar e outra para pedir que ele cancele a instrução. A função de salto também precisará de uma combinação e cancelamento da função de salto dois. O objetivo principal dessas funções é definir variáveis que serão verificadas pela árvore de animação para que ela saiba para quais estados viajar. Na parte superior do script, adicionaremos mais variáveis para indicar intenções do personagem sobre o que ele quer fazer a seguir, entradas armazenadas em buffer como booleanos, se ele quer pular ou atacar Em seguida, a função de ataque definirá a variável want to attack como verdadeira e cancelar o ataque a retornará como falsa. Como a entrada está sendo armazenada em buffer, não precisamos mais exigir que o personagem possa se mover ou ficar no chão, e podemos delegar essa responsabilidade à máquina de estado das árvores de animação E também não precisamos fazer com que a reprodução da máquina de estado da árvore de animação viaje para o estado inicial Faremos com que essa transição seja automática se as condições forem atendidas. Mas não queremos que essas duas variáveis sejam verdadeiras ao mesmo tempo. O personagem vai querer pular ou atacar, não os dois. Portanto, sempre que uma entrada em buffer for definida como verdadeira, todas as outras serão definidas como falsa, substituindo a falsa, substituindo Na cena do personagem, selecionando a árvore de animação e alternando para o painel da árvore de animação, podemos ver a máquina de estado. Vamos mudar a transição da locomoção para o salto e começar a ser automática, com a condição de que o personagem esteja no chão, possa se mover e queira Agora, o personagem pulará automaticamente assim que puder, dentro de 1 segundo após pressionar o botão de pular. Isso é particularmente útil para encadear saltos um após o outro, já que o jogador poderá pressionar o botão de pular antes de cair no chão Mas, olhando para a máquina de estado de salto, vamos considerar como incorporar as animações de ataque Poderíamos fazer a transição da locomoção para o ataque e vice-versa Mas as animações ficariam ruins se quiséssemos que o personagem pudesse se mover enquanto ataca Eu não permitiria que o personagem atacasse enquanto pulava. Em vez disso, seria melhor separar as animações que envolvem mover o personagem das de execução de ações Se sua máquina de estado ainda não tiver sido salva como um recurso do projeto, clique no menu suspenso ao lado da raiz da árvore e selecione Salvar como. Eu já salvei a minha na pasta de cenas de personagens e a chamei de animações de personagens Mas vou renomeá-lo para movimentos de personagens. Com a máquina de estado salva, vamos removê-la da árvore de animação do personagem e, em vez disso, substituí-la por uma árvore de combinação de nós de animação. O painel da árvore de animação agora exibe um gráfico, que conterá nossa árvore de mesclagem, permitindo combinar qualquer quantidade de animações Clique com o botão direito do mouse no espaço vazio e selecione carregar. Em seguida, navegue pelos recursos do projeto para encontrar a máquina de estados de movimento do seu personagem. A máquina de estado que usávamos anteriormente agora é um nó no gráfico da árvore do Blend, e o resultado da máquina de estado será gerado pelo pino no lado direito. Se conectarmos a saída da máquina de estado à saída da árvore de mesclagem , a animação funcionará exatamente como antes. Mas o objetivo da árvore de mesclagem é combinar várias animações Vamos desconectar o pino. Em seguida, clique com o botão direito do mouse e adicione uma mistura de dois nós. O nó de combinação de dois começará com a animação conectada ao pino de entrada e se misturará em uma porcentagem da animação conectada ao pino de entrada de combinação. O resultado dessa mistura será saída do pino no lado direito, que podemos conectar à saída das árvores de mistura. A animação que queremos misturar com os movimentos do personagem serão as ações do personagem, ou seja, seus ataques. Podemos adicionar outra máquina de estado à árvore de mesclagem e chamá-la de ação. Em seguida, conecte sua saída ao pino de entrada de mistura de dois nós. Em seguida, abriremos a máquina de estado de ação e iniciaremos o personagem na animação ociosa Transição do início para o inativo para torná-lo o estado de ação padrão Em seguida, precisaremos ver nosso personagem e iniciar as máquinas de estado de movimento e ação clicando no botão play em seus respectivos estados iniciais. Em seguida, retorne à raiz da árvore de mistura. Nosso personagem ainda parece estar na animação jump idle porque a porcentagem da animação de ação que está sendo misturada a ela é atualmente zero Se arrastarmos a alça até uma, podemos ver a animação mudar gradualmente de pular inativo para inativo Em seguida, clique no botão Editar filtros e ative a opção Ativar filtragem Vamos tirar a janela do caminho para que possamos ver nosso personagem enquanto filtramos ossos individuais, decidindo em quais ossos nossas animações de ação devem ser aplicadas e quais não Ative todos os ossos que compõem a parte superior do corpo do personagem Agora, a parte inferior do corpo do personagem, incluindo sua posição, está sendo afetada pelo estado do movimento. Pule inativo, enquanto a parte superior do corpo está sendo controlada pelo estado de ação ocioso Isso nos permite combinar essas animações de três maneiras diferentes Se o personagem estiver se movendo, mas não executando nenhuma ação , a quantidade de mistura será zero, usando somente a saída da máquina de estado do movimento. Se o personagem estiver executando uma ação, mas não estiver se movendo, a quantidade de mistura será uma e os filtros serão desativados, usando somente a saída da máquina de estado da ação. Se o personagem estiver se movendo e executando uma ação , os filtros serão ativados. Usando a saída da máquina de estado de movimento para a parte inferior do corpo do personagem e a saída da máquina de estado de ação para a parte superior do corpo. Vamos chamar essa mistura de dois nós inferior e superior, já que ela mistura as animações da parte superior do corpo com as animações inferior do corpo Mas se a quantidade de mistura for zero ou uma, as animações em uma das máquinas de estado não serão executadas para economizar tempo de processamento, que pode resultar em alguns problemas se confiarmos nelas para definir propriedades ou chamar métodos Pode ser útil ter sempre as duas máquinas de estado funcionando o tempo todo, mesmo que o personagem não esteja executando nenhuma ação ou não esteja se movendo. Para garantir que ambas as máquinas de estado estejam sempre ativas, podemos definir a quantidade de mistura para 1% e, ao realizar uma ação, aumentá-la para 99%. Podemos supor que ele deve começar com uma quantidade de mistura de 1% já que o personagem não realizará nenhuma ação quando carregado pela primeira vez. De volta ao roteiro do personagem, como a árvore de animação se tornará muito mais complexa, seria uma boa ideia abstrair seus comportamentos em seu próprio roteiro. Podemos remover a variável de reprodução da máquina de estado do script do personagem e adicionar um novo script à árvore de animação Vou salvá-lo na pasta de scripts de personagens. No novo script da árvore de animação, nosso principal objetivo é criar as três combinações de animação que acabamos de mencionar Na função de processo, precisaremos definir o parâmetro de quantidade de mistura como fizemos com os espaços de mistura. Copiar o caminho da propriedade e especificar uma quantidade de mistura. Vamos transformar a quantidade de mistura em uma variável flutuante privada com um valor padrão de 1% e passar isso como argumento Em seguida, precisaremos alterar o valor da quantidade de mistura com base no fato de o personagem estar ou não realizando uma ação. Vamos armazenar a reprodução das máquinas de estado de ação em uma variável Desta vez, usando a palavra-chave self, já que esse script está anexado à árvore e usando o caminho da propriedade para a reprodução da máquina de estado de ação Em seguida, na função de processo, podemos verificar em qual nó a reprodução do estado da ação está atualmente E se estiver no estado ocioso, isso significa que o personagem não está realizando nenhuma ação e podemos definir a quantidade de mistura em 1% Caso contrário, eles estão executando uma ação e podemos configurá-la para 99%. Mas essa será uma mudança instantânea que pode parecer um pouco Então, em vez de definir a variável diretamente para 1% ou 99%, vamos movê-la em direção a esse número um pouco ao longo do tempo. Usando a função move em direção, podemos começar do que a variável é atualmente, movendo-a em direção ao que queremos que seja por Delta. Isso fará com que a transição demore 1 segundo, o que é um pouco longo. Então, vamos multiplicar Delta por uma nova variável para manter a velocidade de mistura, que darei um valor padrão de quatro A transição levará um quarto de segundo. Para ativar ou desativar os filtros, precisaremos acessar diretamente o nó de combinação de dois. Então, declarar uma variável para mantê-la, que é do tipo animation node blend two Podemos acessá-lo a partir da raiz da árvore de animação, usando a função get node. Essa função aceita um nome de string, que podemos especificar como o mesmo nome que demos ao nó no gráfico da árvore de mistura, inferior mais superior. Tenha cuidado para que a grafia seja exatamente a mesma. Não podemos ativar ou desativar os filtros durante o processamento da árvore de animação. Então, vamos criar uma função pública para permitir que o script do personagem faça isso por nós, dizendo à árvore de animação se o personagem está se movendo ou não. Se o personagem estiver se movendo, os filtros devem estar habilitados para combinar as ações da parte superior do corpo com os movimentos da parte inferior do corpo. Se o personagem estiver parado, os filtros podem ser desativados para usar apenas as animações de ação Enquanto estamos aqui, vamos também adicionar mais duas funções para definir as quantidades de mistura dos espaços de mistura de locomoção para mantê-los abstraídos do script do personagem Defina a mistura bloqueada, aceitando um parâmetro vetorial dois para a quantidade da mistura, definindo o parâmetro da quantidade de mistura do espaço de mistura bloqueado. E defina como não bloqueado na mistura, aceitando um parâmetro flutuante para a quantidade da mistura, definindo o parâmetro da quantidade de mistura do espaço de mistura não bloqueado De volta ao script de caracteres, podemos ver que os caminhos das propriedades para os valores de mistura não são mais válidos, pois não se referem à máquina de estado do movimento. Abstraindo essas funções, manteremos todas as alterações na árvore de animação contidas em seu próprio script No processo normal da física, também precisaremos dizer à árvore de animação se o personagem está ou não se movendo no momento. No entanto, agora estamos assumindo que cada personagem deve ter esse script anexado à sua árvore de animação e que eles estão usando a mesma árvore de animação Então, vamos salvar nossa nova árvore de animação como um recurso do projeto. Vou colocá-lo na pasta de cenas do personagem, junto com a máquina de estado do movimento do personagem. Em seguida, atualize cada um dos outros personagens para usar a nova árvore de animação e anexe o script a ela, para que todos funcionem da mesma maneira. Estou usando apenas o Bárbaro e os esqueletos neste projeto, mas o mago noturno e o ladino também devem ser atualizados se você os estiver usando No entanto, isso cria um novo problema. Se todos os caracteres compartilharem o mesmo recurso de árvore de mistura , a alteração da propriedade enable filters para um caractere a alterará para todos os caracteres. Podemos contornar isso dando cada personagem sua própria cópia exclusiva da árvore de mistura. Para evitar ter que replicar todas as mudanças na árvore de mistura de cada personagem todas as vezes, usarei um atalho simples No script da árvore de animação, durante a função ready, definirei a propriedade raiz da árvore uma duplicata da árvore de mistura Passar true como argumento também duplicará quaisquer subrecursos que esse recurso esteja Como a árvore de mistura, essa árvore de animação está sendo usada, pois sua raiz não é mais a mesma que foi originalmente atribuída. Precisaremos atribuir os valores da reprodução do estado de ação e da combinação de dois nós após essa duplicação Agora, toda vez que um personagem for carregado, ele fará sua própria cópia exclusiva da árvore de mistura e poderá alterar seu comportamento de filtragem sem afetar outros personagens Vamos voltar à máquina de estado de ação dos personagens. Nosso personagem ainda não tem nenhum item equipado, então vamos transformá-lo em ídolo desarmado Por enquanto, vamos estabelecer que a condição para essa transição seja se eles estão mirando em um inimigo ou se querem atacar usando um cruzamento curto, e eles podem voltar se não estiverem mirando em um inimigo e não quiserem Depois, para manter as coisas organizadas. Adicione também outra máquina de estado chamada ataques desarmados e faça a transição para a máquina de estado se o personagem quiser atacar Eles podem então voltar para o ídolo desarmado no final da animação de ataque Editando a máquina de estado desarmada. Vamos começar com o soco de ataque masculino desarmado A. Isso fará a transição para o final ou para soco de ataque masculino desarmado B no final da animação, com base no fato de o personagem querer ou não Podemos repetir esse padrão fazendo a transição para um chute de ataque masculino final ou desarmado no final da animação, com base no fato de o personagem querer ou não atacar E podemos criar uma combinação infinita de ciclismo voltando ao primeiro golpe, desde que o jogador continue pressionando o Quando eles pararem de pressionar o botão de ataque, a máquina de estado fará a transição para o fim, que voltará ao modo inativo desarmado Talvez também queiramos restringir a forma como o jogador se move enquanto ataca Por exemplo, não faria nenhum sentido o personagem se movesse durante a animação do chute, já que seus pés deveriam estar ocupados. Vou ampliar a exibição da faixa de animação para ajustar melhor a duração dessas animações. Vamos adicionar uma função pública ao script do personagem para restringir o movimento, aceitando um parâmetro booleano para determinar se o personagem pode ou não se mover Em seguida, definiremos o valor da variável de movimento como o oposto. Na animação de chute do personagem. Podemos adicionar uma faixa de método de chamada chamando um método no nó raiz do personagem. Chamando a função de restrição de movimento no início da animação, passando true como argumento, restringindo o movimento do personagem ao chutar E outra tecla no final da animação pode restaurar a habilidade de movimento do personagem alterando o argumento para falso. Mas para que isso funcione, precisamos retornar à árvore de mesclagem e adicionar funções aos filtros de combinação de dois nós para que, se o personagem estiver se movendo e executando uma ação, as funções de ações sejam chamadas. Vamos experimentar. Nossas animações parecem estar funcionando como antes Assim que mandamos o personagem atacar, ele passa para o estado ocioso desarmado antes de realizar um Se continuarmos clicando, eles continuarão atacando repetidamente, percorrendo as diferentes animações de ataque desarmado É até possível se mover ou pular enquanto ataca, e o personagem usará as animações apropriadas para a parte superior e inferior do corpo, mas não poderá se mover ou pular enquanto Se nos fixarmos em um alvo, o personagem passa para o estado ocioso desarmado e o bloqueio volta para o ídolo normal Agora temos nosso personagem realizando ataques desarmados. Na próxima lição, adicionaremos animações de ataque com armas. Te vejo na próxima aula. 6. Arma: Olá, amigos. Na lição anterior, combinamos ações da parte superior do corpo com movimentos da parte inferior do corpo, permitindo que nosso personagem realize ataques desarmados Nesta lição, também adicionaremos uma variedade de animações de ataque com armas Vamos começar na árvore de animação dos personagens, onde já temos ataques desarmados, ociosos e desarmados Seguindo esse padrão, adicionaremos a animação inativa em duas mãos Neste pacote de ativos, não há animações inativas com uma mão ou duas rodas Mas podemos simplesmente adicionar duas novas cópias da animação ociosa e renomeá-las A partir de cada uma dessas animações inativas, podemos nos conectar a máquinas de estado de ataque que funcionam exatamente como os ataques desarmados Conectando-se de cada uma das animações inativas aos ataques, se o personagem quiser atacar, e retornando no final da Só precisamos de uma maneira de dizer ao personagem qual conjunto de animações usar com base na arma equipada Neste projeto, temos um script chamado enums, contendo todas as nossas enumerações, ao qual adicionaremos Começando com desarmado como padrão, depois listando cada um dos diferentes tipos de armas que precisam de animações diferentes, mala de uma mão, mala de duas mãos e roda dupla É importante saber que a enumeração é apenas uma lista numerada, então cada um desses valores são na verdade números, começando com desarmado sendo zero, uma mão é uma, duas mãos é duas e roda dupla é três e No script do personagem, adicionaremos outra variável chamada animação de ataque com um tipo de nossa nova enumeração Podemos exportar essa variável para fins de teste. Vamos mudar a animação de ataque do personagem para algo diferente de desarmado Vou usar combate corpo a corpo com duas mãos. De volta à máquina de estado de ação, podemos definir a condição de transição de inativo para inativo desarmado para ser se animação de ataque do personagem for zero, o que está desarmado em nossa enumeração, e também pelo menos uma das outras condições colocando-as entre A condição de devolução também será oposta. Ou a animação do ataque não é zero ou as outras duas condições são atendidas. Adicionando transições a cada um dos diferentes estados de inatividade, podemos definir suas condições para serem as mesmas de inatividade desarmada, usando apenas um valor diferente para Também darei a cada um deles o mesmo tempo de cross fade. Em seguida, voltando ao modo inativo sob condições logicamente opostas Dentro de cada uma das máquinas de estado de ataque, podemos usar as animações de ataque da mesma forma que fizemos com os ataques desarmados Existem quatro ataques diferentes com uma mão, criando um ciclo de animações diferentes , desde que o personagem queira continuar atacando Repetir o mesmo processo para ataques com duas mãos, que têm apenas três ataques diferentes E a máquina de estado de duas rodas também tem apenas três ataques Podemos testar isso no jogo, já que a animação de ataque dos personagens está configurada para duas mãos, eles usam as animações de ataque com duas mãos Podemos dizer a eles que usem animações de ataque com uma mão ou animações de duas rodas . Agora, só precisamos mudar a variável ao equipar itens para o personagem Nos recursos personalizados, precisaremos de uma classe mais específica para descrever uma arma herdada do equipamento Dando a ela o nome de classe arma, podemos adicionar uma variável extra exportada para armazenar o tipo de arma e podemos usar a mesma enumeração do Então, qualquer um dos recursos do item do projeto que são armas pode ser reclassificado como arma, dando a eles um valor para o tipo de arma, o personagem saiba quais animações usar ao equipá-las Para fins de demonstração, atualizarei o x para ser uma arma de uma mão. Lembre-se de preencher novamente todos os campos que não foram transferidos ao alterar o script do recurso O grau como arma de duas mãos e o punhal como arma de duas rodas No int ou qualquer script que você esteja usando para equipar itens, precisaremos de uma exceção para se o item que está sendo equipado for E se for uma arma de duas mãos ou uma arma de dupla empunhadura , precisaremos remover qualquer coisa o personagem tenha equipado em seu espaço externo Verifique primeiro se o arquivo, a matriz de equipamentos de progresso tem algo equipado no slot improvisado Em seguida, usarei isso para indexar os botões do item no inventário do jogador e remover o E de equipado do botão. Em seguida, defina também o valor das matrizes do equipamento para menos um ou vazio Em seguida, direi ao personagem que qualquer equipamento em seu soquete manual No roteiro do personagem, o personagem precisará saber o que está segurando nas mãos. Vamos adicionar variáveis do tipo nó três D para segurar o equipamento principal e não manual. Nosso personagem usando uma arma também pode ter lógica extra adicionada para determinar se o item for uma arma O item principal da mão do personagem pode então ser atribuído a essa arma, e as animações de ataque dos personagens podem ser configuradas para coincidir com as da arma que está sendo equipada Se o item for uma arma do tipo roda dupla, também adicionarei outra cópia duplicada da arma no soquete manual do personagem E atribua-a à variável improvisada. Ao retirar um equipamento, se esse equipamento estiver sendo removido da mão principal do personagem, podemos definir a variável da mão principal como nula e também verificar se ela está usando se esse equipamento estiver sendo removido da mão principal do personagem, podemos definir a variável da mão principal duas armas no momento Se estiver empunhando duas vezes, direi ao personagem que também faça o item de improviso E então eu vou definir a animação do ataque para desarmado. Da mesma forma, se o soquete que está sendo desligado estiver desligado, devemos definir a variável improvisada Não precisamos mais exportar a animação do ataque, pois agora ela será definida pela arma equipada. Agora, o personagem começa a usar ataques desarmados. Mas quando equipado com uma arma de uma mão passa a usar ataques com uma mão. Podemos equipá-los com um escudo, depois mudar para uma arma de duas mãos, e o escudo será removido automaticamente O personagem agora usa animações de ataque com duas mãos. Mudando para os punhais de duas rodas, o personagem tem um punhal nas duas mãos e usa as animações de ataque de duas e usa Ao equipar os punhais, personagem volta a usar ataques desarmados A última coisa que nossos ataques precisam são caixas de quadril. Áreas de colisão para detectar se o ataque realmente atinge um inimigo e causa dano Abrindo as cenas das armas, podemos adicionar caixas de acerto a cada uma delas. Usando um nó D de área três, que não será monitorado ou monitorado por padrão, nem terá nenhuma camada de colisão ou máscara de colisão até que sejam instruídos a fazê-lo Como esses modelos de personagens têm membros curtos e armas pequenas, seus ataques não chegam muito longe Então, vou ser muito generoso com suas caixas de quadril, tornando-as maiores do que as armas reais. Criando um novo script para as armas, herdando do item Vou substituir o script anexado ao nó raiz da arma e abri-lo para edição. Podemos dizer à arma que pegue ou faça referência à caixa de acerto usando o complemento pronto. Em seguida, adicione funções para definir a máscara de colisão das caixas de acerto para um novo número inteiro E outra que ativará ou desativará a caixa de acerto definindo sua propriedade de monitoramento O personagem que segura essa arma agora pode especificar em qual camada de colisão seus inimigos estão e ativar a caixa de acerto ao balançar a O modelo do personagem também precisará uma caixa de quadril para ataques desarmados Assim como as armas, elas não precisam ser monitoradas, monitoráveis, nem ter uma camada de colisão ou máscara de colisão e terão uma forma de colisão de grandes dimensões Mas não precisamos posicioná-lo agora e podemos delegar essa responsabilidade às animações No script do personagem, podemos obter uma referência à caixa do quadril desarmada usando addon ready Lembre-se de adicionar um quadril a cada caractere ou usar a função get node ou null para evitar erros Também vamos exportar uma camada física de três D para conter a camada de colisão dos inimigos desse personagem Isso adicionará uma grade de números no inspetor, assim como as camadas de colisão nas propriedades das três notas D. Dessa forma, podemos especificar que esse personagem tentará atingir coisas na camada de colisão inimiga de Hurt, que eu disse ser a camada 18 Enquanto isso, inimigos usando o mesmo script podem definir sua camada de colisão inimiga como a camada colisão HRT do jogador Durante a função de preparação, podemos definir a máscara de colisão da caixa do quadril desarmada como a camada de colisão do inimigo Da mesma forma, sempre que uma arma é equipada, podemos configurar sua máscara de colisão para ser a camada de colisão do inimigo, ele saiba quais camadas mascarar , independentemente de quem a esteja Em seguida, precisaremos de algumas funções no script do personagem para ativar e desativar as caixas do quadril das armas durante as animações de ataque, aceitando um parâmetro booleano para especificar se a caixa do quadril está sendo ativada ou desativada e um número inteiro E eu vou dar a ela um valor padrão de um para significar a mão principal. Usando uma declaração de partida, podemos criar três casos separados, ativando a caixa do quadril para ataques desarmados, ataques mão principal ou ataques improvisados Se estiver desarmado, podemos definir a propriedade de monitoramento da caixa do quadril desarmada Se for mão principal ou improvisada , podemos dizer à arma ative ou desative sua caixa de acerto As animações de nossos personagens podem então ter faixas adicionadas a elas para ativar e desativar as caixas de sucesso Vou demonstrar apenas com um ataque de cada tipo, começando com um golpe de ataque masculino com uma mão. Ao adicionar uma faixa de método de chamada a essa animação, geralmente esperaríamos que a caixa de acerto fosse ativada logo após começar a girar Adicionando uma chave neste momento, podemos mudar o argumento booleano para verdadeiro para ativar a caixa de acerto da arma principal do personagem Em seguida, desativado no final do swing, alterando o argumento para false Isso evitará que inimigos entrem na arma quando ela não estiver se movendo e não sejam feridos por ela, e só causará dano quando o personagem estiver realmente balançando a arma com força O processo é o mesmo ao empunhar uma arma nas mãos Adicionar uma faixa e, em seguida, função de enquadramento de teclas ativa a caixa de acerto no início do giro da arma e desativá-la no final do Ao empunhar duas vezes, precisaremos especificar qual caixa do quadril está sendo ativada, se é a mão principal ou a mão livre, alterando também o parâmetro inteiro para dois, se a caixa do quadril que está sendo ativada ou desativada pertencer à arma improvisada E quando desarmados, precisaremos não apenas ativar a caixa do quadril, mas também posicioná-la no local correto Usando uma trilha de propriedades para enquadrar a propriedade de posição das caixas de quadril. Em seguida, alteraremos o argumento inteiro nas chamadas de função para zero para indicar que queremos usar a caixa do quadril desarmada É uma boa ideia verificar se a caixa do quadril está posicionada em pelo menos uma estrutura antes de ativá-la É útil usar vistas ortogonais para posicionar a caixa do quadril exatamente no punho do personagem em pelo menos dois ângulos Em seguida, clique no ícone da chave para enquadrar essa posição na animação. Não poderemos testar essas caixas de quadril até a próxima aula, quando adicionarmos caixas feridas para elas atingirem. A caixa do quadril não só será ativada com a animação, mas também seguirá o punho do personagem Lembre-se de que você precisará concluir esse processo para cada animação de ataque. Agora temos nosso personagem atacando com animações diferentes para cada tipo de arma Na próxima lição, permitiremos que os personagens se machuquem e sofram danos. Te vejo na próxima aula. 7. Hit: Olá, amigos. Na lição anterior, adicionamos caixas de acerto às nossas armas e animações de ataque Nesta lição, adicionaremos caixas de Hurt aos nossos personagens para que eles possam ser atingidos por ataques. A caixa Hurt de um personagem é apenas mais um nodo D da área três. Vamos adicionar aos modelos de personagens. Eles não serão monitorados, mas serão monitoráveis pelas caixas de sucesso Eles existirão na camada da caixa de ferimento do jogador ou na camada da caixa cardíaca do inimigo de forma adequada Mas não precisa mascarar nada pois eles não estão monitorando de qualquer maneira. Para a forma de colisão das caixas Hert, outra cápsula é muito comum, mas geralmente é menor que a forma de colisão corporal do personagem e totalmente contida no modelo do Não seria justo que o jogador fosse atingido por algo que parece não fazer contato. Lembre-se de que as armas estão usando caixas de quadril grandes, então as caixas cardíacas serem menores também seria razoável, mas vou fazer com que as minhas caibam na cabeça e no corpo do personagem Em seguida, copiarei e colarei a mesma caixa de coração nas cenas do meu personagem inimigo, mudando sua camada de colisão para a camada HRT inimiga Então, em nossas cenas de armas, usarei o machado como exemplo Precisaremos conectar o sinal de área inserida da caixa de acerto ao script da arma. Se a caixa de acerto dessa arma entrar na caixa de ferimento de um personagem , precisaremos dessa arma para causar dano a esse Por enquanto, vamos adicionar uma variável pública para o dano causado por essas armas. Quando a colisão acontecer, precisaremos de uma referência ao personagem ao qual a caixa Hurt pertence No meu projeto, esse sempre será o nó principal da caixa Hurt. Podemos então dizer ao personagem que sofra dano, passando o dano da arma como uma discussão. Também pode ser bom saber de onde vem o dano. Assim, podemos usar a diferença entre suas posições globais normalizadas Para manter todas as informações de nossas armas em um só lugar, seu dano deve ser adicionado ao arquivo de recursos como uma variável exportada, e eu darei a ele o valor padrão de dois danos Cada arquivo de recurso de arma diferente pode então especificar quanto dano essa arma causará Lembre-se de conectar também o sinal da área inserida para cada cena de arma. Da mesma forma, a caixa de quadril desarmada do nosso personagem também precisa uma conexão de sinal para instruir o personagem a causar dano desarmado Pegar o pai da Hurt Box e pedir que eles sofram um dano e forneçam a direção normalizada Então, no script do personagem, quando criamos a instância da arma, podemos definir seu dano o mesmo número do recurso. I. Enquanto estamos aqui, vamos também escrever a função de receber dano na região de combate. Aceitando a quantidade de dano a ser sofrida, bem como a direção de onde o dano está vindo, dando a ele um valor padrão de vetor 30. Para sofrer danos, nossos personagens precisarão de saúde. Vou adicionar uma categoria de exportação para as variáveis de combate. Em seguida, declare um para a saúde máxima dos caracteres como um número inteiro, que definirei E sua saúde atual também como um número inteiro, que podemos definir como sua saúde máxima usando addon ready Também vamos declarar alguns parâmetros booleanos para determinar se o personagem está morto ou não e se o dano sofrido foi causado por trás, e também obter uma referência à caixa rt do personagem usando addon ready Ao sofrer dano, a saúde atual do personagem será reduzida pela quantidade de dano recebido, mas não queremos permitir que ela fique abaixo de zero. Portanto, podemos usar a função max para configurá-la para esse cálculo ou zero, o que for maior O booleano de trás pode então ser definido como verdadeiro se o produto escalar da direção do dano com o vetor de base direta das plataformas de caracteres for um número negativo Se a saúde atual do personagem após sofrer dano for zero, ele morrerá. Caso contrário, eles serão atingidos. Embora a animação de morte seja automática, a animação de sucesso pode ser gerenciada pelo script das árvores de animação, e informaremos se o dano recebido estava abaixo ou acima de um determinado limite Dessa forma, podemos alterar a animação do golpe com base na quantidade de dano recebido. Também podemos monitorar a saúde de um personagem ou quando ele morre. Seria uma boa ideia transmitir esses dois eventos como sinais. Declarando um sinal para sempre que a saúde do personagem mudar, podemos usar uma porcentagem da saúde restante como argumento e outro sinal para quando o personagem morre Em seguida, emita o sinal de mudança de saúde se eles sofrerem danos e o sinal de morte se o personagem morrer Para calcular a porcentagem de saúde restante, basta dividir a saúde atual pela saúde MX Mas como esses dois valores são inteiros, o resultado também será um número inteiro, portanto, resultará apenas em zero ou Precisaremos fazer com que pelo menos um deles flutue primeiro antes de realizar a divisão, para que o resultado também surja Se não quisermos mais que personagens mortos sejam afetados por colisões, também podemos definir sua camada de colisão como zero, sua máscara de colisão como uma, para que eles sejam afetados apenas pelo terreno e definir sua propriedade monitorável H rtbach Também é possível que um personagem seja atingido ou morto enquanto executa uma ação. Portanto, também devemos acompanhar quais ações interrompidas podem causar problemas e corrigi-las em uma função privada Por exemplo, provavelmente deveríamos desligar todas as caixas do quadril se seus ataques fossem interrompidos, o que também podemos fazer em uma função separada, verificando se existem referências a cada uma antes de desativá-las Na árvore de animação dos personagens, queremos que o personagem que está morrendo ou sendo atingido interrompa e substitua todas as outras Como essa árvore de combinação já está salva como um recurso, podemos removê-la da árvore de animação e substituí-la por uma máquina de estado. No nível mais básico da máquina de estado, começaremos com as animações de morte de nossos personagens, já que elas terão a maior prioridade absoluta sobre todas as outras animações Em seguida, adicione outra máquina de estado para as animações de sucesso. Faremos a transição do golpe para a morte A se o personagem estiver morto. Com um pequeno crossfade. Ou, alternativamente, à morte B, se eles também forem atingidos por trás dando prioridade a essa prioridade , definindo-a como zero. Talvez não seja necessário nosso personagem volte da morte, mas não faz mal adicionar a transição com a condição de que ele não esteja morto. Dentro da máquina de estado de acertos, faremos algo semelhante com as animações de sucesso e adicionaremos nossa árvore de mesclagem como animação padrão aqui Ativando as transições para as animações de sucesso e retornando à árvore de mesclagem no final de suas Com um crossfade dentro e fora das animações de sucesso, com a máquina de estado da árvore de animação atualizada, vamos salvá-la como um recurso do projeto Vou chamá-la de animações de personagens. E pela última vez, cada personagem pode ser atualizado para usar a nova máquina de estado. No script Animation trees, precisaremos de uma referência à reprodução do estado de ocorrência Além disso, como atualizamos o formato da árvore, precisaremos atualizar todos esses caminhos de propriedades. Agora acessaremos o nó de mesclagem obtendo o nó atingido, depois o nó da árvore de mistura e, finalmente, o nó inferior e superior da mistura de dois nós. Dando uma definição à função get hit, podemos receber o parâmetro booleano como se o personagem está sendo atingido levemente ou não Em seguida, diga ao estado de impacto que deve viajar para atingir A se for atingido levemente ou atingir B se for atingido com mais força. Vamos experimentá-lo. Se socarmos o esqueleto, eles reagem ao serem atingidos levemente, equipando um machado e Eles são atingidos com mais força. Um terceiro golpe e eles morrem, caindo para trás desde que foram atingidos pela frente Podemos equipar o grande machado, que eu configurei para causar um dano de cinco e matar outro esqueleto por trás, e ele cair para frente ao morrer Também seria bom poder rastrear a saúde do personagem do jogador na interface do usuário. Vamos adicionar um nó de controle e chamá-lo de medidor de saúde. Vou colocar isso por trás de todo o resto na interface do usuário. Isso precisará de um texto direto para desenhar a borda, uma cor ereta como preenchimento e outro texto direto se quisermos um ícone Vou usar uma moldura deslizante fina como imagem da borda. É muito grande, então vou reduzi-lo para um quarto de seu tamanho. E eu vou usar o ícone, um pequeno coração cheio para o ícone. Redimensione-o e posicione-o onde fique bem em relação à borda Em seguida, definirei a cor ect para combinar com a cor do coração e definirei sua posição e dimensões para preencher o medidor Vou redefinir sua propriedade de tamanho, ancorá-la no canto inferior esquerdo Clicando e arrastando na propriedade tamanho x do preenchimento, podemos ver como o medidor pode ser facilmente configurado para qualquer porcentagem Anexando um script ao medidor de saúde, podemos simplesmente chamá-lo de medidor para reutilizá-lo em qualquer outro medidor Obteremos uma referência à cor de preenchimento ret usando add on ready e também declararemos uma variável para manter o tamanho ponto x do preenchimento quando o medidor estiver completamente preenchido, que é a configuração da propriedade size dot x quando carregada pela primeira vez Em seguida, escreva uma função pública chamada set value, aceitando um parâmetro de porcentagem flutuante Tudo o que precisamos fazer é definir a propriedade size x da cor t como a porcentagem multiplicada pelo tamanho máximo Conectando o sinal de mudança de saúde do personagem do jogador à função de valor definido dos medidores, ele agora rastreará automaticamente a saúde do jogador Para testar o medidor de saúde. Vou apenas dizer ao personagem que sofra dois pontos de dano toda vez que o jogador pressiona o botão de execução Agora podemos ver o medidor de saúde do personagem se esgotar e o personagem morrer quando está vazio Em seguida, reiniciarei a linha de absorção de danos para voltar a funcionar. Agora temos nosso personagem sendo atingido e sofrendo danos causados por ataques. E na próxima lição, permitiremos que os personagens evitem ser atingidos por esquiva Te vejo na próxima aula. 8. Dodge: Olá, amigos. Na lição anterior, permitimos que nossos personagens fossem atingidos por ataques, sofressem danos e morressem. Nesta lição, vamos ajudá-los a evitar danos ao se esquivar. Vamos começar nas configurações do projeto, na guia Mapa de entrada, adicionando um evento de entrada para se esquivar Vou usar a barra de espaço ou o botão direito do meu controle. No script do jogador, podemos usar os mesmos métodos de pular e atacar para amortecer a entrada de esquiva No script do personagem, precisaremos de uma variável para determinar se o personagem quer ou não se esquivar Mas uma esquiva não é apenas uma entrada simples. Também requer uma direção como vetor três. Na região de combate, precisaremos de uma função de esquiva e uma função de cancelamento de esquiva, configurando a variável booleana E com qualquer entrada armazenada em buffer, todas as outras entradas em buffer serão Como já estamos armazenando a direção de entrada no script do personagem, podemos verificar se esse é o vetor 30 no momento em que o personagem foi instruído a se esquivar Se não der nenhuma contribuição, quero que o personagem se esquive para trás Vou usar o vetor dianteiro das bases das plataformas de caracteres, multiplicando-o por menos um para revertê-lo Se estivermos dando uma entrada direcional, quero que o personagem se esquive nessa direção, mas sempre com força total Vou normalizar a direção para remover a magnitude da equação Na máquina de estado da árvore de animação dos personagens, navegando pelas animações de morte e sucesso até a árvore de mistura e, finalmente, a máquina de estado do movimento Podemos adicionar as animações de esquiva em um espaço de mesclagem bidimensional Transição de locomoção para esquiva se o personagem quiser se esquivar e de volta à locomoção Ambos com um cross fade. Como isso se conecta à locomoção, a esquiva só será realizada enquanto o personagem estiver no chão Você também pode querer ter esquivas aéreas conectadas ao estado de inatividade do salto Dentro do espaço de mesclagem do Dodge, alterarei o ajuste da grade para fatores de um Em seguida, adicione as animações Dodge forward, Dodge backward, Dodge left e dodge right que serão misturadas para que o personagem possa se esquivar em qualquer direção. O script da árvore de animação precisará ser capaz de definir a quantidade de mistura desse espaço de mesclagem como um vetor dois, da mesma forma que definimos a quantidade de mistura das animações bloqueadas no strafing De volta ao script do personagem, ao mandar o personagem se esquivar, podemos fazer com que a animação defina essa quantidade de mistura Mas a direção da esquiva é um vetor três no espaço global, enquanto a quantidade de mistura da esquiva é um vetor dois no espaço local das plataformas de caracteres Podemos calcular a quantidade de mistura comparando a direção de esquiva com os vetores de espaços da plataforma usando um Vou precisar reverter a quantidade de mistura x multiplicando-a por menos Se experimentarmos isso, a animação de esquiva reproduzida três vezes e o personagem não está realmente se movendo A animação se repete porque o desejo de se esquivar é válido por um segundo inteiro, mas a animação dura apenas 0,4 segundos. Portanto, ela se repetirá quantas vezes puder até que a variável want to dodge volte a ser falsa antes que o 1 segundo termine Precisaremos definir a variável como falsa depois que a esquiva for executada com sucesso e também aplicar alguma velocidade para mover o personagem Adicionando outra função, assim como aplicar a velocidade de salto, aplicaremos a velocidade de esquiva e chamaremos essa função a partir da animação Se essa função for chamada, o caractere foi evitado com sucesso e podemos definir a variável como falsa para evitar que mais esquivas ocorram a partir de uma única entrada Em seguida, definiremos a velocidade do personagem como a direção de esquiva multiplicada pela força de esquiva Isso criará um impulso repentino de velocidade, movendo o personagem rapidamente na direção em que ele está se esquivando Criando outra variável exportada para a força de esquiva do personagem Vou ajustá-lo para oito. Também pode querer que nosso dodge tenha molduras para os olhos, abreviação de molduras de invencibilidade Esse é um período de tempo em que o personagem não pode ser ferido por ataques Assim como temos uma função chamada por nossas animações de ataque para ativar ou desativar a caixa do quadril, também teremos uma função chamada pelas animações de esquiva para ativar e desativar a caixa Hurt Devemos usar set deferred para definir a propriedade monitorável da caixa Hurt para o valor de active caso isso esteja acontecendo durante um Como é possível que queiramos chamar essa função como resultado de uma colisão, não possamos ativar ou desativar os colisores enquanto eles estão sendo processados Nas animações dos personagens, precisaremos adicionar faixas de chamada de função a cada uma das animações de esquiva de nossos personagens Primeiro vou desligar a caixa Hurt do personagem. Então, quando o personagem parecer que está começando a se mover na animação, aplicarei a velocidade de esquiva Quando eles tiverem algum tempo para a velocidade do Dodge tire o personagem do caminho do ataque, eu ligarei a caixa HRT novamente mudando o argumento Em seguida, repita o mesmo conjunto de chamadas de função para cada uma das animações de esquiva Embora isso não deva acontecer com esse código como está atualmente, pode ser possível que o personagem interrompido enquanto se esquiva, significa que a caixa de alimentação talvez nunca seja Dependendo de como o jogo funciona, talvez você queira incluir a ativação da caixa do personagem nas ações de interrupção. Agora que a velocidade de esquiva está sendo aplicada, eu realmente não gosto de como a animação de esquiva realmente move a posição raiz da plataforma do personagem, resultando em alguns movimentos abruptos, tanto na entrada quanto Então, abrindo as animações, removerei os quadros-chave raiz das animações de esquiva Manter o equipamento do personagem enraizado onde o personagem deveria estar, conforme determinado pela física do corpo do personagem E então vou repetir isso para as outras animações de esquiva também Executando o jogo, podemos ver a árvore da cena remota, encontrar a caixa de arte do personagem e prestar atenção à propriedade monitorável esquiva define a propriedade monitorável como falsa, depois a redefine como verdadeira, e o personagem anima a esquiva de forma mais suave com a velocidade, graças à remoção dos quadros-chave raiz Com a esquiva agora animada e funcionando corretamente, vamos agora considerar se queremos permitir que o personagem ataque e se esquive ao mesmo tempo Além disso, o personagem deve poder atacar ou se esquivar se for atingido Se não quisermos permitir esse comportamento, precisaremos rastrear quando o personagem está atacando, se esquivando ou sendo Vamos adicionar mais algumas variáveis booleanas ao nosso script de personagem: está atacando, esquivando e sendo Tudo isso precisará ser exportado para ficar acessível ao nó do player de animação Usando faixas de propriedades, as animações de ocorrência podem definir a variável de ocorrência verdadeira no início da animação E voltando ao falso no final. Então, na árvore de animação, ao fazer a transição da locomoção para a esquiva, podemos verificar se o personagem quer se esquivar e nada é atingido e nada está ao fazer a transição da locomoção para a esquiva, podemos verificar se o personagem quer se esquivar e nada é atingido e nada está atacando. Antes de passar para qualquer estado de ataque, podemos verificar não apenas se o personagem quer atacar, mas também se ele não foi atingido e não está se Podemos então repetir o processo de configuração das variáveis booleanas nas animações de esquiva Cada um define a variável de esquiva verdadeira no início e falsa no final Novamente, com cada animação de ataque, defina a variável de ataque como verdadeira no início das animações de ataque e quedas no final Caso ataques ou esquivas sejam interrompidos, também devemos definir essas variáveis como falsas Também existe a possibilidade de o personagem morrer interrompendo a animação de sucesso Então, definiremos a variável is hit como false aqui. Para que a variável de ataque seja definida pela máquina de estado de ação, também precisaremos habilitar o filtro para ela e também a posição da caixa de acerto Para testar se a esquiva está realmente funcionando, precisaremos que os inimigos comecem a atacar Se você ainda não configurou as animações de ataque do inimigo, uma maneira fácil de fazer isso é copiar o reprodutor de animação do personagem e colá-lo na cena inimiga Em seguida, podemos dizer à árvore de animação que use o novo reprodutor de animação. E desde que o inimigo tenha a mesma estrutura óssea do personagem, todas as animações funcionarão da mesma forma Caso contrário, você precisará configurar o inimigo para ter pelo menos um ataque capaz de ativar uma caixa de quadril, mascarando a caixa t do personagem Para fazer o ataque do inimigo, basta anexar um nó em branco a ele na cena do nível. Com um script simples, mandando eles atacarem. Vou criar uma nova pasta para scripts inimigos e chamá-la de ataque. Depois de pegar uma referência ao personagem como pai desse nó, direi ao personagem que ataque na função pronta Como a variável nunca voltará a ser falsa, isso é tudo o que é necessário para que os inimigos realizem ataques sem parar Vamos tentar rodar o jogo com formas de colisão visíveis ativadas E veja a árvore da cena remota, onde podemos ver os valores de todas as nossas novas variáveis. O personagem aguardará o término de um ataque antes de realizar uma esquiva e vice-versa. Se deixarmos o esqueleto atingir o personagem, ele sofrerá danos e não conseguirá atacar ou se esquivar até que a animação de golpe termine E podemos evitar o ataque do esqueleto com nossa nova ação de esquiva Agora temos nosso personagem se esquivando para evitar ataques e restringindo quando o personagem pode realizar Na próxima lição, permitiremos que os personagens bloqueiem os ataques recebidos com um escudo Te vejo na próxima aula. 9. Bloqueio: Olá, amigos. Na lição anterior, ajudamos nossos personagens a evitar danos ao se esquivar de ataques Nesta lição, permitiremos que eles bloqueiem ataques com um escudo. Vamos começar nas configurações do projeto, na guia Mapa de entrada, e adicionar um evento de entrada para bloqueio. Vou usar o botão direito do mouse e o botão esquerdo do ombro no meu controle. No script do jogador, o botão de bloqueio não precisa ser armazenado em buffer, pois se comporta mais como o botão de execução, alterando o comportamento do personagem enquanto o botão Enviar um sinal para o personagem bloquear ou não, com base no fato de o botão ser pressionado ou solto. O script de caracteres pode então armazenar esse valor em uma variável. Quer bloquear. Mas, diferentemente das outras variáveis, não há necessidade real de armazenar em buffer a entrada de bloqueio Em seguida, adicione uma função na seção de combate que defina essa variável. Na máquina de estado da árvore de animação dos personagens navegando até a máquina de estado de ação Podemos adicionar a animação do bloco e fazer a transição a ela se o personagem quiser bloquear com um pequeno crossfade Em seguida, faça a transição de volta para se eles não quiserem bloquear. Obtendo uma visão do personagem e misturando-se ao estado de ação, essa animação faz com o personagem levante o escudo Quando a animação estiver concluída, podemos fazer a transição para a animação de bloqueio, que deve ser configurada em loop para manter o escudo levantado, desde o jogador mantenha pressionado o botão de bloqueio. Isso também voltará ao modo inativo se o personagem não quiser mais bloquear com um pequeno crossfade Talvez também queiramos fazer a transição para a animação em bloco de alguns de nossos outros estados ociosos, como os estados desarmado e ocioso com uma mão Para reduzir o número de transições, primeiro combinarei os estados ocioso e inativo com uma mão combinando logicamente as condições de transição para alcançar o estado de ataque com uma Se a animação de ataque for uma, eles querem atacar e não são atingidos nem se esquivam Em seguida, volte ao modo inativo no final da animação do ataque. Excluindo o estado ocioso de uma mão, reorganizarei os outros estados para ficarem um pouco mais Agora, um ídolo ocioso ou desarmado pode fazer a transição para o bloqueio, se o personagem quiser bloquear, e voltar diretamente para o desarmado, se a animação de ataque do personagem for zero, ele tiver um alvo ou quiser atacar, mas não Com prioridade zero. Agora, tanto o ocioso quanto o ocioso desarmado podem fazer a transição para bloqueio se o personagem quiser bloquear Os estados de bloqueio e bloqueio podem pular a inatividade e retornar diretamente à inatividade desarmada com prioridade zero Dessa forma, o personagem não precisa passar por dois estados de inatividade diferentes entre bloquear e atacar Se experimentarmos, nosso personagem pode fazer a transição para a animação em bloco ao pressionar o botão de bloqueio e voltar ao modo inativo quando o botão de bloqueio for solto Mas faria mais sentido restringir o personagem a usar essa animação somente se ele tiver um escudo equipado. Para fazer isso, precisaremos de outro script de recursos. Herdando do equipamento, dando a ele o nome de classe de escudo Se você quiser que seus escudos tenham variáveis diferentes, podemos defini-las aqui. Vamos adicionar uma variável para a quantidade de dano reduzida pelo bloqueio com esse escudo com o valor padrão de um. Acessando o recurso personalizado de escudos redondos bárbaros. Podemos transformá-lo em um escudo e alterar a quantidade de redução de dano, se quisermos. Lembre-se de repreencher todas as propriedades que foram redefinidas como resultado dessa alteração de classe e atualizar todos os escudos para usar o novo Na cena do escudo, precisaremos ser capazes de armazenar as variáveis do recurso do item no escudo assim como fizemos com a arma. Adicionando um novo script, ele terá apenas uma variável inteira de redução de danos e uma função fictícia de ativação do quadril, que ignorará o argumento booleano e Ficará claro por que isso é necessário em um minuto. Em seguida, podemos substituir o script anexado ao nosso escudo pelo novo. No script do personagem, vamos adicionar outra variável à categoria de equipamento para determinar se o personagem tem ou não um escudo equipado. Ao vestir um equipamento, se o item for um escudo, definiremos que seja o equipamento improvisado, repassaremos o valor de redução de dano do recurso do item para o escudo e configuraremos o escudo equipado como verdadeiro Como a variável improvisada agora está segurando um escudo em vez de uma arma, interromper as ações do personagem desativará todas as caixas de quadril E como o improviso não é nulo, estamos pedindo que ele desative a caixa do quadril Mas dissemos ao escudo que ignorasse esse pedido. Então, ao tirar um equipamento, se o soquete for de improviso, podemos supor que o personagem não está mais segurando um escudo não está mais Então, ao mandar o personagem bloquear, podemos adicionar a condição de que o personagem também tenha um escudo equipado. O script de inventário também precisará mais algumas condições ao equipar um escudo para evitar que o personagem equipe um escudo quando sua mão improvisada já estiver ocupada com uma arma de duas mãos ou fora de mão Esse processo variará dependendo como seus sistemas de inventário e equipamento funcionam. Se o item selecionado for um escudo e o personagem tiver algo equipado na mão principal e o personagem estiver usando as animações de duas mãos ou de duas rodas, desequiparei o soquete principal e direi ao personagem que remova o equipamento com a mão principal direi ao personagem que remova o equipamento com a equipamento Se experimentarmos. O botão de bloqueio agora é ignorado se o personagem não tiver um equipamento de escudo. Podemos equipar uma arma de duas mãos depois equipar o escudo. A arma de duas mãos é desequipada automaticamente e, em seguida, o escudo é equipado E agora o personagem pode bloquear com o escudo. A seguir, vamos considerar como a entrada de bloqueio funciona com nossas outras ações. Se o jogador estiver bloqueando e decidir atacar ou se esquivar , eu gostaria que essas ações tivessem prioridade na interrupção do Mas se definirmos a variável de desejo de bloquear como falsa , o jogador terá que soltar o botão de bloqueio e pressioná-lo novamente para continuar bloqueando. Em vez disso, podemos declarar outra variável booleana. Vamos chamar isso de bloqueio de interrupção. Se o personagem quiser atacar ou se esquivar, essa variável pode ser definida como verdadeira E quando o ataque ou a esquiva terminar, podemos voltar para falso para permitir que o personagem continue bloqueando automaticamente Vou simplificar a função add dodge velocity para apenas chamar cancel Em seguida, na árvore de animação, podemos adicionar as condições para sair do bloco ou bloquear para incluir se o bloco está sendo interrompido E não permita que as transições voltem ao bloco até que o bloqueio não seja mais interrompido Agora, o personagem deixará de bloquear enquanto estiver atacando e retornará automaticamente ao bloqueio enquanto o botão de bloqueio ainda estiver pressionado E o mesmo também funciona para se esquivar. A última coisa que precisamos fazer é realmente reduzir o dano dos ataques recebidos durante o bloqueio Para isso, precisaremos saber se o personagem está bloqueando. Como o bloqueio não se limita a uma única animação e aos loops de animação, não há como simplesmente dizer animador que defina uma variável booleana como verdadeira Vamos adicionar a animação de sucesso em bloco. Permitindo que a transição para essa animação bloqueada e retornada no final da animação. O que contratamos para saber se o personagem está bloqueando é em qual estado essa máquina de estado está atualmente. Se estiver no estado de bloqueio ou bloqueio , o escudo do personagem está levantado. A animação do bloco também é bastante longa. Inclui não apenas levantar o escudo, mas também um ciclo de animação de bloqueio. Não acho que o personagem deva ser considerado bloqueado até que o escudo esteja totalmente levantado, mas também não quero esperar que a animação do bloco termine. Então, no reprodutor de animação do personagem, vou reduzir a duração da animação do bloco para fazê-la parar depois que o escudo for levantado em um terço de segundo. No script de árvores de animação, vamos adicionar uma função pública para verificar se o personagem está bloqueando, retornando um booleano Primeiro, armazenar o nome do nó atual dos estados de ação em uma variável de string. Podemos retornar se estiver bloqueando ou bloqueando. E também precisaremos de outra função para reproduzir a animação de impacto do bloco, fazendo que o estado da ação viaje até o estado do bloqueio atingido. Em seguida, no script do personagem, na parte superior da função de receber dano. Podemos verificar se a animação do personagem está bloqueada no momento e se a direção vem o dano é a frente do personagem. Usando um produto escalar da direção do dano com o vetor de base frontal do personagem rigs Se o valor for um número positivo, o dano está vindo de algum lugar na frente deles. Porém, isso cobriria um ângulo amplo, uma meia esfera inteira na frente do personagem. Usando algo próximo a um quarto ou meio, podemos limitá-lo à forma de um cone. Nessas condições, o ataque deve ser bloqueado com sucesso, reduzindo a quantidade de dano pela redução do dano do escudo. Usando a função max para limitá-la a um mínimo de zero. Podemos então dizer à árvore de animação que reproduza a animação de golpe de bloco e, se a quantidade de dano for completamente reduzida para zero, eu retornarei, pois o personagem não está sofrendo nenhum dano. Vamos experimentá-lo. Equipando o escudo e bloqueando o ataque do esqueleto O dano é reduzido a zero e a animação do golpe no bloco é reproduzida. Sofrendo danos pela lateral ou pelas costas, o personagem ainda sofre danos. Agora temos nosso personagem capaz bloquear ataques com um escudo na frente. Na próxima lição, daremos a eles uma arma de longo alcance que pode disparar projéteis Te vejo na próxima aula. 10. Fotografe: Olá, amigos. Na lição anterior, permitimos que nosso personagem bloqueasse ataques com um escudo. Nesta lição, daremos a eles uma arma arranjada capaz de disparar projéteis Este pacote de ativos não contém um parafuso para a besta, então vou começar criando um na cena da besta Começando com um corpo rígido de três nós D , renomeando-o como parafuso Vou posicioná-lo onde a base do parafuso ficará dentro da besta, com seu vetor de base z azul apontando para frente, onde ele será disparado Em seguida, adicionarei uma instância de malha de três nós D como filho, preenchendo-a com a malha cilíndrica Reduzindo o raio e a altura, girando-os para apontar para frente e posicionando-os para frente ao longo do eixo z. Vou apenas dar um material básico e definir o albedo para uma cor marrom Em seguida, adicione um nó básico de três D como outro filho, para que ele seja colocado na mesma posição e rotação e renomeie seu soquete de amplificador Em seguida, repare o soquete na besta, mantendo essa Recolocando o parafuso no soquete do amplificador, forma que sua posição e rotação em relação ao seu pai agora sejam O raio agora pode ser transformado em sua própria cena, que vou colocar em uma nova pasta para projéteis e depois excluí-la da cena da besta Agora, a besta pode ser carregada simplesmente adicionando um parafuso como filha desse O parafuso precisará de uma forma de colisão. Vou usar uma cápsula com as mesmas dimensões e posição do cilindro. Expandindo a seção do solucionador, precisarei ter o monitor de contatos ativado e o máximo de contatos definido como algo maior que zero Se quisermos que o parafuso colida com o terreno, ele precisará mascarar a primeira camada de colisão E eu quero que meus parafusos se movam lentamente para que eu possa ver o que eles estão fazendo Mas não quero que eles caiam devido à gravidade. Então, vou definir sua escala de gravidade para zero. Anexando um script ao parafuso, podemos chamá-lo de projétil, ele possa ser usado para outros tipos de projéteis em nosso jogo e salvá-lo na pasta de scripts do item Assim que um parafuso for instanciado, ele será carregado na E talvez queiramos passar informações do personagem ou da arma para a munição neste momento Vamos criar uma função pública para fazer isso. Mas, por enquanto, vamos definir sua propriedade de congelamento como verdadeira, já que o corpo rígido não precisa fazer nada até que a arma seja disparada Para disparar o projétil, aplicaremos uma força de impulso enviada pela arma como um vetor três Nesse momento, o corpo rígido pode começar a aplicar a física para mover o parafuso pela cena do jogo, definindo sua propriedade de congelamento Não queremos mais que o projétil siga as propriedades de transformação de seu progenitor, a besta Ele deve ser adaptado ao cenário do jogo, onde ele pode se mover e agir livremente Caso não esteja apontando diretamente para a direção em que está sendo disparado, podemos dizer ao parafuso que olhe para um ponto no espaço que seja sua própria posição global menos a direção da força de impulso Em seguida, aplique a força de impulso no parafuso para que ele se mova nessa direção Conectando o sinal inserido pelo corpo do corpo rígido ao script, essa função será chamada se o parafuso entrar em contato com qualquer coisa na primeira camada de colisão, o terreno Se isso acontecer, o parafuso pode ficar exatamente onde entrou em contato, redefinindo sua propriedade de congelamento como verdadeira, mas adiada, pois isso acontece durante uma colisão É muito importante que, sempre que você implementar um recurso em um jogo que instancia um grande número de nós, você também implemente alguma forma de limpá-los Caso contrário, você pode acabar com quantidades muito grandes que fazem com que as taxas de quadros caiam e, eventualmente, travem o jogo. Uma prática comum com projéteis é dar a eles uma vida útil máxima Vamos adicionar um nó de tempo aos nossos projéteis e configurá-lo para contar uma vez Vou configurá-lo para 10 segundos. Em seguida, pegue uma referência à hora ou ao nó usando addon ready. Iniciaremos o cronômetro ao disparar o projétil. Se não atingir nada, ainda queremos limpá-lo, para que não voe para longe para sempre Conectando o sinal de tempo limite ao script do projétil. Isso fará com que o projétil seja libertado da cena do jogo De volta à cena da besta, precisaremos de um novo roteiro para essa arma Podemos chamá-la de arma de longo alcance e colocá-la na pasta de scripts do item Substitua o script anexado a essa arma por uma arma de longo alcance e forneça uma referência ao arquivo de recursos personalizado da besta Podemos exportar a munição como uma cena lotada, uma peça pré-fabricada que podemos usar como modelo para instanciar quantas precisarmos Em seguida, atribua o parafuso como munição para a besta no inspetor Precisaremos de uma referência ao soquete de munição usado estiver pronto e de uma referência à munição que está atualmente carregada na Também pode ser bom ter um bônus de dano que a arma adicionará aos tiros disparados como um número inteiro A quantidade de força de impulso que a arma aplica à munição quando é disparada enquanto Usarei um número baixo, como dez, para que possamos ver os parafusos se movendo facilmente pelo ar e a máscara de colisão de nossos inimigos para que as informações possam ser passadas do personagem, da arma para a munição Ao equipar a arma, personagens estão configurando a caixa do quadril, máscara de colisão das armas, para que possamos facilmente reutilizar a mesma função para definir a variável da E assim como fizemos com o escudo, podemos adicionar uma função para ativar a caixa do quadril, ignorando esse parâmetro, e simplesmente retornar Já que a arma não tem caixa de quadril própria. A arma precisará ser capaz de disparar o projétil com uma função pública, e deixaremos o personagem especificar a direção em que deseja que o projétil vá como parâmetro Tudo o que a arma precisa fazer é passar essa chamada de função para o amo, multiplicando a direção pela força da arma Em seguida, defina a referência de amo carregada nula, já que a arma não está mais carregada, e uma função de recarga, que instanciará um novo parafuso, atribuindo-o Em seguida, adicione-o como se fosse filho do soquete do amplificador, dando-lhe a posição e a rotação corretas necessárias para se encaixar bem na besta Podemos então transmitir qualquer informação a munição precise saber antes de ser disparada, como os danos da arma e a máscara de colisão Então, vamos adicioná-los como parâmetros à função onload no script do projétil Nosso script de personagem precisará de uma variável para saber se a arma que eles estão segurando está carregada no momento. E duas novas funções, recarregar e disparar. Recarregar, apenas definirá a variável como verdadeira e, em seguida, dirá à arma principal que recarregue Por enquanto, atirar apenas definirá a variável como falsa e, em seguida, dirá à arma principal que atire em uma direção, passando o vetor base do equipamento do personagem para frente Se a arma não estiver equipada, pois está sendo completamente removida da árvore da cena, a munição também será removida junto com Então, vou redefinir a variável da arma carregada de volta para falsa neste momento. nossa enumeração de tipos de armas, precisaremos de mais duas entradas para o alcance de ataques com uma mão, que será o número quatro, e ataques de alcance com duas mãos No recurso personalizado de bestas, mudarei o script de equipamento para arma Vou mudar o tipo de arma para o alcance de uma mão, diminuir o dano e repovoar seu ícone E, da mesma forma, mude a besta pesada para o alcance de duas mãos Na árvore de animação dos personagens, precisaremos de mais ações para ataques à distância. Essa máquina de estado já está ficando muito grande e bagunçada, então vou incluir os ataques de alcance outra máquina de estado Fazendo a transição para essa máquina de estado, se os personagens atacarem animação for de quatro ou cinco, e eles quiserem atacar, serem atingidos nem Em seguida, volte ao modo inativo no final da animação. E vou misturar as duas transições com um pouco de cross fade. Dentro do alcance para atacar a máquina de estado, podemos adicionar animações para fotografar e recarregar Tanto para ataques de alcance com uma mão quanto com duas mãos. Só precisamos jogar a correta uma vez e depois voltar para a máquina de estado de ação. Então, todos eles farão a transição no final. As transições para uma mão exigirão que a animação de ataque seja definida para quatro E duas mãos ajustadas para f. A reprodução das animações de tiro ou de recarga será baseada no valor da arma carregada Agora que as animações podem ser reproduzidas pela árvore de animação, precisamos que as animações chamem funções no script do personagem Durante a animação de filmagem, adicionaremos um método chamado track and scrub ao quadro antes que o personagem recue do projétil que está sendo disparado Em seguida, adicione um quadro-chave para chamar a função de captura. Da mesma forma, durante a animação de recarga, tentaremos selecionar um quadro quando o personagem terminar de recarregar a arma E adicione um quadro-chave à trilha do método de chamada para realmente recarregar a arma Se quisermos que essas animações impeçam o personagem de realizar outras ações, precisaremos definir uma variável booleana como fizemos com os ataques Vou apenas reutilizar a variável está atacando. E repita também para as animações de longo alcance para duas mãos . Vamos experimentá-lo. Podemos equipar a besta para o personagem e, pressionando o botão de ataque uma vez, faremos com que ele carregue a besta com Pressionando o botão de ataque pela segunda vez, eles disparam a besta para frente, e o raio dispara até atingir algo no ambiente, onde para e se destrói após Agora precisamos dos parafusos para causar dano aos inimigos. De volta à cena do parafuso, precisaremos adicionar uma caixa de acerto ao parafuso A caixa de impacto precisa de uma forma de colisão. Vou usar a esfera. Vou posicioná-lo na outra extremidade do parafuso e dar-lhe um raio menor Assim como nossas outras caixas de quadril, ela ainda não precisa ser monitorada ou ter uma máscara de colisão Pegando uma referência à caixa do quadril usando at on ready, vamos também exportar uma variável para os danos nos parafusos Vou usar o valor padrão de um. Quando o parafuso é carregado na besta pelo personagem, seria uma boa oportunidade para passar informações, como quaisquer bônus de dano e a máscara de colisão O bônus de dano da arma pode ser adicionado ao dano dos parafusos, e a camada de colisão da caixa do quadril pode ser definida como a camada de colisão inimiga do personagem Quando o projétil é disparado, podemos dizer à caixa do quadril que comece a monitorar as caixas de rebanho inimigas Conectando o sinal inserido na área da caixa do quadril ao script do projétil Podemos dizer à caixa Hurt que esse projétil atingiu para fazer com que seu personagem principal sofresse dano Da direção das caixas Hurt, a posição global menos a posição global do Bolt foi normalizada O parafuso pode então ser removido da cena. E se o parafuso atingir o terreno, ele não deve mais ser monitorado para causar dano, então vamos configurá-lo como falso No roteiro do personagem, eu gostaria de ter certeza absoluta de que, quando o personagem está preso em um alvo, o projétil é disparado diretamente contra esse alvo Portanto, a função de tiro se dividirá em dois comportamentos diferentes com base no dois comportamentos diferentes com base no fato de o personagem estar ou não preso a um alvo, chamando uma função separada para atirar em um alvo, passando o alvo como argumento. Mas a arma só deve disparar contra o alvo do bloqueio se o personagem estiver de frente para ele. Assim, podemos verificar se o produto escalar do vetor de base direta das plataformas de caracteres e a diferença normalizada em suas posições globais é um número positivo Quanto mais próximo do positivo, quanto mais parecidos eles são, mais o personagem fica voltado para eles. Eu direi que algo maior que 0,75 está perto o suficiente para atirar no alvo do bloqueio. No script de armas de longo alcance, definindo atirar no alvo, aceitando um alvo como parâmetro Agora podemos calcular a direção como a diferença das posições da gaiola normalizada e multiplicada pela força Como isso usará a posição tubal da arma, não a posição gubal do personagem, a direção será mais precisa E vou adicionar 1 metro até a posição do alvo para não mirar em seus pés. Vamos experimentá-lo. Equipando uma arma de longo alcance e bloqueando um alvo, primeiro vou me virar para o lado, e o projétil ainda dispara para frente, já que o personagem não está de frente para o Movendo-se para encarar o alvo e disparando um segundo raio, desta vez ele atira diretamente no alvo e causa dano Agora temos projéteis sendo disparados de armas de longo alcance, atingindo inimigos ou Na próxima lição, permitiremos que os inimigos detectem jogadores e reajam. Te vejo na próxima aula. 11. Inimigo: Olá, amigos. Na lição anterior, adicionamos ataques de alcance que disparam projéteis Nesta lição, permitiremos que os inimigos detectem, perseguam e ataquem o personagem do jogador. Na cena do cemitério, adicionamos um nó simples que diz ao inimigo que ataque constantemente Vamos remover isso e começar a criar uma versão mais complexa para atacar apenas quando o personagem do jogador estiver ao alcance de ser atingido. Na cena do esqueleto dos lacaios, adicionaremos um nó filho do tipo nó três D, pois ele precisará acessar três posições e rotações D. Vou chamar isso de agressão. Em seguida, adicione um nó D de área três, que representará o alcance de ataque do inimigo. Vou dar a ele uma forma de colisão e usar uma esfera. Ajustando o tamanho da esfera para ser um pouco maior, darei a ela um raio de 1 metro e, em seguida, posicionarei a 1 metro acima do solo e 1 metro A área de alcance de ataque monitorará colisões que mascaram a caixa de rebanho do jogador Vamos anexar um script a esse nó e colocá-lo na pasta de scripts do inimigo. Como o objetivo desse script é controlar um personagem exatamente como o nó manipulador de entrada do jogador, precisaremos de uma referência ao personagem está sendo controlado por esse nó Com a forma como estou estruturando minha árvore de cena, esse nó sempre será filho direto do nó do personagem, então eu posso acessar o personagem chamando get parent. Conectando os sinais da área inserida e da área de saída ao script, renomearei os parâmetros e fornecerei renomearei os parâmetros os tipos para Quando Hurt box do personagem do jogador entra no campo de ataque, queremos dizer ao inimigo que ataque. E quando a caixa Hert sai do campo de ataque, podemos dizer ao inimigo que não Podemos salvar essa ramificação como sua própria cena e salvá-la na pasta de cenas inimigas. Em seguida, exclua-o dessa cena inimiga. E De volta à cena do cemitério, podemos conectar nosso nó de agressão inimigo a qualquer um ou a todos os nossos inimigos para que eles ataquem automaticamente o personagem do jogador se entrarem no campo de ataque personagem do jogador se entrarem no campo Vamos experimentá-lo. Os inimigos ainda não estão atacando, mas atacaremos se entrarmos seu alcance de ataque e pararemos quando sairmos dele Em seguida, permitiremos que os inimigos vejam o personagem do jogador a uma distância maior. Abrindo a cena do nodo de agressão, podemos adicionar outro nodo D da área três para representar a visão de um inimigo Adicionando uma forma de colisão a essa cena, usarei outra esfera com um raio muito maior Vou usar 5 metros e posicioná-lo para ficar à frente do inimigo e um pouco acima do chão. Essa área pode monitorar a camada de colisão do personagem do jogador Vou usar a camada nove. Em seguida, adicione um raio de três nós D para ser sua linha de visão e também mova-o para fora do chão. Isso procurará a mesma camada do campo de visão, mas também estará obstruído pelo Como usei a camada nove, que é o corpo do personagem e não a caixa t, conectarei os sinais de entrada e saída do corpo ao script de agressão Quando um corpo entra no campo de visão, eu o armazeno em uma variável, vamos chamá-lo de alvo do tipo corpo do personagem três D. Mas também precisaremos confirmar se eles também têm uma linha de visão clara antes de se tornarem agressivos. Então, precisaremos de uma referência ao elenco. E podemos armazenar se o inimigo viu ou não o jogador em uma variável booleana também vamos pegar uma referência ao Agora também vamos pegar uma referência ao campo de divisão do inimigo. A. Usando a função de processo, podemos começar verificando se o valor do alvo foi definido. Se for nulo, o inimigo não poderá ver o personagem do jogador Deveríamos simplesmente voltar. Se o inimigo ainda não viu o jogador , podemos verificar sua linha de visão em relação ao alvo. Definir a posição alvo do raycast como a diferença em suas posições globais, adicionando um metro acima do solo Depois de forçar o raycast a atualizar se está colidindo com algo e se algo com o qual está colidindo é o alvo , a linha de visão não é Podemos definir a variável has seen player como verdadeira. Se o valor dessa variável for verdadeiro, comportamento do inimigo mudará e faremos com que ele persiga o personagem do jogador. Quando o personagem do jogador sai do campo de visão do inimigo, se o corpo é o alvo e o inimigo ainda não viu o jogador , não precisamos mais verificar sua linha de visão, para que possamos definir o alvo como nulo Esse nó de agressão é filho do nó do personagem, que não está girando Portanto, o campo de visão e alcance de ataque não girarão com o equipamento do personagem Podemos usar a referência de caracteres para pegar a rotação do anel, acessar a propriedade y e atribuí-la à rotação y desse nó. Então, ele seguirá a mesma rotação. Talvez também queiramos uma maneira de dizer a esse inimigo que pare de perseguir o personagem do jogador Nesse caso, podemos definir o alvo como nulo, ver o alvo como falso e dizer a esse personagem que se mova sem direção Um bom momento para chamar essa função seria quando o inimigo morresse. Então, substituindo a função pronta. Podemos conectar o sinal morto desse personagem à função de parada. Quando o inimigo vê o personagem do jogador pela primeira vez, também podemos conectar o sinal de morte do alvo à função de parada para impedir que o inimigo tente matar o personagem do jogador depois de ele já ter morrido. Também usarei essa mesma função para desligar a visão desse inimigo, definindo sua propriedade de monitoramento como falsa. Para que o inimigo se mova em direção ao jogador, primeiro precisamos fazer algumas mudanças em nossa cena de nível. Vamos adicionar três nós D da região de navegação ao nível. Em seguida, recrie quaisquer nós que serão usados para gerar nosso mapa de navegação como filhos desse nó, incluindo o solo e os obstáculos. Feito isso, selecione o nó da região de navegação e preencha a malha de navegação com uma nova malha de navegação Em seguida, clique no botão da malha de navegação Bake. A malha de navegação cobrirá o terreno com triângulos que formam uma área onde os personagens poderão andar Expandindo o recurso de malha de navegação, podemos ver suas propriedades. A única seção preocupante no momento é a seção de agentes. Agentes são nossos personagens que usarão essa malha de navegação para percorrer a cena. Dando uma olhada rápida nas cápsulas de colisão de nossos personagens, atribuí a elas uma altura de 2,6 metros e um raio de 0,75 Vou copiar esses valores para a altura e o raio dos agentes recurso de medida de navegação e, em seguida, refazer a malha de navegação A malha agora deixa mais espaço entre paredes e obstáculos. Para usar a região de navegação, todos os nossos personagens precisarão outro nó anexado a eles, um agente de navegação com três nós D. Certifique-se de anexar um a cada personagem. Obtendo uma referência a esse nó usando addon ready. Em seguida, podemos escrever uma função no script de caracteres, que pode ser usada para dizer a qualquer personagem que navegue até qualquer local na malha de navegação por qualquer motivo. Isso também é muito útil para muitas coisas fora do combate. Aceitando uma posição alvo como um vetor três, definiremos a posição alvo do agente de navegação a mesma localização. O agente de navegação usará automaticamente a malha de navegação, atribuída à mesma camada de navegação para produzir um caminho para chegar o mais próximo possível do local de destino. Fazendo com que os agentes obtenham a próxima posição do caminho, retornaremos o primeiro ponto intermediário ao longo desse caminho como um vetor três. Podemos então subtrair a posição global atual do personagem para obter um vetor apontando de onde estamos para a primeira posição ao longo do caminho Se multiplicarmos isso por 101 para remover o componente vertical, normalizaremos esse vetor Agora é funcionalmente equivalente a um vetor de entrada produzido pelo nosso script de manipulação de entrada do player quando o player inclina o analógico ou usa as Então, podemos atribuir isso à variável de direção de entrada. E o processo físico cuidará do resto, mandando o personagem percorrer esse caminho, que o levará até o alvo. Seria uma boa ideia transferir tudo o que acontece com um personagem quando ele morre para uma função pública, caso algo além de sofrer danos possa fazer com que ele morra. Quando um personagem morre, devemos dizer a ele que pare de se mover. E quando eles são instruídos a se mover ou realizar qualquer ação, devemos ignorar essas solicitações se o personagem estiver morto ao retornar. De volta ao roteiro de agressão, só precisamos dizer ao inimigo que navegue em direção ao alvo depois de vê-lo Antes de experimentar, vamos escolher um inimigo. Vou usar o guerreiro esqueleto e selecionar seu agente de navegação Three D node. Na seção D Bug, clique em habilitar Toggle para poder ver o caminho renderizado aproximarmos do primeiro esqueleto, assim que entramos em seu campo de visão, a linha de visão imediatamente confirma que eles podem nos ver, e o agente de navegação encontra um caminho para o inimigo caminhar Então nos ataque. Derrotar esse inimigo, desta vez, vamos atrair a atenção do ladino Como eles estão atrás da lápide, a linha de visão não foi confirmada e o inimigo permanece escondido E se nos aproximarmos do guerreiro, podemos correr ao redor da cova aberta, vendo como o agente de navegação atualizará automaticamente o caminho em tempo real, para percorrer o caminho mais curto possível para alcançar o jogador Talvez também queiramos que nossos inimigos sejam capazes de empunhar armas De volta à cena do cemitério, vamos conectar outro nó básico a um de nossos inimigos e chamá-lo Anexando um script a esse nó, eu o colocarei na pasta de scripts do inimigo Tudo o que precisamos fazer é pegar uma referência ao nó principal, o personagem, e exportar uma arma para equipar esse personagem Em seguida, na função pronta, diga ao personagem para usar a arma. Vou dizer ao meu guerreiro esqueleto que equipe um grande machado. Em seguida, copie e cole esse nó em outro inimigo e troque a arma por outra coisa. Vou dar algumas facas ao bandido. Cada uma das cenas de nossos inimigos precisará ter nós de fixação óssea adicionados a elas. Seguindo a fenda da mão esquerda e a fenda da mão direita. Podemos então preencher o conjunto de soquetes do equipamento do personagem com esses nós para serem usados ao equipar armas Por fim, seria bom não precisar recarregar o jogo quando morrermos Então, vamos conectar o sinal morto do personagem do jogador ao script do gerenciador do jogo. Depois de ficar preto, vou pedir à árvore de cenas que recarregue a cena atual, redefinindo tudo de volta ao que estava quando a cena foi carregada pela primeira Vamos experimentá-lo. O guerreiro esqueleto está equipado com o grande a e está usando as animações de ataque com duas mãos Quando morremos, toda a cena é recarregada. E, desta vez, enfrentando o ladino, eles estão equipados com facas e usam animações de duas rodas Agora temos um sistema de combate complexo em nosso jogo com uma variedade de mecânicas que podem ser ajustadas para atender às necessidades do seu jogo