Domine o Godot 4: crie um roguelike de sobreviventes usando o GDScript | Chris Tutorials | Skillshare

Velocidade de reprodução


1.0x


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

Domine o Godot 4: crie um roguelike de sobreviventes usando o GDScript

teacher avatar Chris Tutorials, Game Developer

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 ao curso

      1:43

    • 2.

      Configuração do projeto no Godot

      6:38

    • 3.

      Arte, som e plugins ~ Importação e instalação

      8:46

    • 4.

      Movimento de cima para baixo do jogador

      34:39

    • 5.

      Reproduza animações a partir do Spritesheets

      9:51

    • 6.

      Máquina de estado do jogador

      18:49

    • 7.

      Entrada do jogador como componente

      13:08

    • 8.

      Troque animações com sinais

      9:17

    • 9.

      Virando um personagem 2D

      13:41

    • 10.

      Camadas de mapas com grama e terra

      16:38

    • 11.

      Usando árvores como adereços de mapa

      15:16

    • 12.

      Adicionando estampas e corrigindo classificação Y

      9:41

    • 13.

      Projéteis gerados com um cronômetro

      14:54

    • 14.

      Mova os projéteis na direção do lançamento

      6:25

    • 15.

      Configurando inimigos e Hitboxes

      16:55

    • 16.

      Causando dano aos inimigos com Hitboxes e Estatísticas

      9:14

    • 17.

      Estado de morte quando o inimigo alcança 0 HP

      13:59

    • 18.

      Rotação e direcionamento dos projéteis com carga de arma

      5:43

    • 19.

      Adicionando efeitos sonoros e música

      7:21

    • 20.

      Singleton

      5:48

    • 21.

      Como animar texto de combate flutuante

      18:26

    • 22.

      Movimento do inimigo com rastreamento de jogadores no Godot 4

      16:53

    • 23.

      Criando inimigos em uma curva do tempo

      15:36

    • 24.

      Spawn Off Screen com Deslocamento calculado

      19:25

    • 25.

      Aparelhamento de inimigos aleatórios com condições de peso e tempo

      15:11

    • 26.

      Configuração do hurtbox do jogador e do hitbox do inimigo

      7:09

    • 27.

      Cronômetro de invencibilidade do jogador e definições de estatísticas personalizadas

      10:45

    • 28.

      Implementando dano periódico para Hitboxes do inimigo

      4:35

    • 29.

      Derrota de jogadores

      7:40

    • 30.

      Testando e aprimorando o comportamento em derrotas de jogadores

      5:06

    • 31.

      Criando a cena Pickup2D

      6:00

    • 32.

      Implementando um sistema de captação de experiência com herança

      4:42

    • 33.

      Configurando o Collector2D e corrigindo animações do player

      5:24

    • 34.

      Criação de mecânica de lançamento de inimigo e redimensionamento de captadores

      11:32

    • 35.

      Gerando posições aleatórias de itens

      4:45

    • 36.

      Implementando uma área de gravidade de captação

      10:31

    • 37.

      Criando uma UI de jogador com barras de progresso HP e EXP.

      11:15

    • 38.

      implementando um sistema de UI baseado em estatísticas com sinais

      10:38

    • 39.

      Criação de scripts de exibições dinâmicas de HP e EXP para a interface do usuário

      16:06

    • 40.

      Depurando e otimizando scripts de UI e captação

      5:11

    • 41.

      Como nivelar o sistema com experiência e progressão de estatísticas

      18:39

    • 42.

      Configurar limites de XP e conexões de sinal para recompensas de nível

      9:47

    • 43.

      Como aprimorar o layout da UI e o texto animado

      8:39

    • 44.

      Criando uma interface de usuário para seleção de recompensa e ajustes finais

      8:35

    • 45.

      Como criar um sistema de nivelamento de armas para atualizações de jogos

      9:55

    • 46.

      Itens de armas para aumentar o poder das suas armas

      13:24

    • 47.

      Criar um sistema de seleção de itens ponderado para aumentar as recompensas

      14:30

    • 48.

      Seleção de recompensa com propagação de sinal

      18:35

    • 49.

      Aplicando estatísticas de nível de arma ao gerador de projéteis e instâncias

      10:03

    • 50.

      Construindo uma arma de xito rotativa

      10:21

    • 51.

      Criando uma interface de usuário de exibição de armas para inventário de jogos

      19:40

    • 52.

      Conectando sinais e configurando armas na interface do usuário para exibição dinâmica

      19:31

    • 53.

      Criando itens de reforço de estatísticas para atualizações de jogadores

      11:14

    • 54.

      Como implementar captadores HP Boost e aprimorar as correções da interface do usuário

      10:33

    • 55.

      Criando um captador de poção saúde para soltas inimigas

      5:23

    • 56.

      Implementando o tremor da câmera para efeitos de ataque e morte do jogador

      10:14

    • 57.

      Criando uma tela de jogo com o menu principal de navegação

      8:29

    • 58.

      Rastreamento de alta pontuação e exibição de UI para derrotas de inimigos e tempo de sobrevivência

      17:15

    • 59.

      Salvando e carregando partituras altas com JSON

      13:54

    • 60.

      Como criar um menu principal com exibição de alta pontuação e funcionalidade de início de jogos

      11:22

    • 61.

      Aprimorando o script de sobreviventes ~ Melhorias de jogabilidade e depuração

      16:34

  • --
  • 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.

128

Estudantes

1

Projeto

Sobre este curso

Quer criar seu próprio jogo de batalha automático Roguelite repleto de ação, mesmo que seja iniciante em programação?

Este curso fácil para iniciantes guia você passo a passo na criação de um jogo 2D completo — Script Survivors — usando Godot 4 e GDScript, linguagem de script poderosa e fácil para iniciantes do Godot. Sem a necessidade de experiência anterior com programação ou desenvolvimento de jogos, você aprenderá na prática e construirá um protótipo refinado do zero!

O que você vai aprender:

  • Domine o básico e as práticas recomendadas do GDScript: escreva um código limpo e reutilizável com convenções de nomenclatura adequadas (por exemplo, snake_case), variáveis de exportação para ajustes fáceis e scripts de autodocumentação usando comentários para manutenção.

  • Crie uma mecânica essencial de jogo: implemente armas de ataque automático (como lanças e felças), sistemas de geração de inimigos com curvas de dificuldade ajustáveis, coleção de experiência (EXP) e um sistema dinâmico de nível de jogadores com atualizações impactantes.

  • Aproveite o sistema de cenas e nós do Godot: organize seu jogo usando cenas para modularidade (por exemplo, jogador, inimigos e cenas de mundo), nós para objetos de jogo (CharacterBody2D, Sprite2D) e cronômetros para um agendamento preciso de eventos.

  • Crie sistemas de combate envolventes: crie mecânica de saúde e dano, incluindo formas de colisão para interações precisas, quadros de invencibilidade e atualizações de armas com vários alvos para um jogo satisfatório.

  • Adicione polonês com sistemas de UI e salvo: crie interfaces de usuário intuitivas (por exemplo, exibições de alta pontuação, telas de elevação de nível) usando nós de controle e implemente um sistema de salvo/carregamento baseado em JSON para rastrear pontuações altas de inimigos derrotados e tempo de sobrevivência.

  • Use máquinas de estado para lógica mais inteligente: utilize o plug-in Limbo AI para gerenciar comportamentos de personagens e inimigos (por exemplo, estados de inatividade, fuga, ataque), simplificando a lógica complexa e preparando você para padrões avançados de IA.

  • Aplique padrões reais de desenvolvimento de jogos: aprenda habilidades transferíveis como encapsulação (por exemplo, scripts GameManager e SaveLoad), gerenciamento de recursos (por exemplo, PlayerContext) e organização de projetos para escalabilidade para projetos maiores.

Ao final deste curso, você vai:

  • Tenha um jogo de ação 2D totalmente jogável com inimigos, atualizações e um menu principal, pronto para ser exibido em seu portfólio.

  • Navegue com confiança no editor do Godot, do gerenciador de projetos ao inspetor, e use ferramentas como o AnimationPlayer e texturas do atlas para visuais perfeitos em pixels.

  • Esteja preparado para criar seus próprios jogos com uma base sólida no Godot 4, GDScript e fluxos de trabalho de desenvolvimento de jogos, pronto para enfrentar novos projetos com facilidade.

Por que este curso?

  • Para iniciantes: começa do básico, com explicações claras da interface do Godot, sintaxe do GDScript e conceitos de desenvolvimento de jogos, garantindo uma curva de aprendizagem suave.

  • Aprendizagem prática: acompanhe para criar “Script Survivors”, um protótipo completo com arte de pixels, música chiptune e efeitos sonoros, guiado por exemplos práticos.

Habilidades no mundo real: aprenda técnicas profissionais como máquinas de estado, serialização de JSON e design modular, preparando você para projetos de desenvolvimento de jogos maiores.

Comece agora e comece a criar jogos de ação viciantes que fazem os jogadores voltarem por mais!

Conheça seu professor

Teacher Profile Image

Chris Tutorials

Game Developer

Professor

I believe the best way to learn technology--and programming in particular--is through video-based learning. My role is to provide clear, hands-on video tutorials that guide you step-by-step, but ultimately, it's up to you to engage actively, absorb the concepts, and practice consistently. This approach helps you become a more confident and skilled developer.

I specialize in Godot game development using GDScript and C#, breaking down complex topics into manageable lessons that empower you to build your own projects from the ground up.

If you want to experience my teaching style before enrolling, check out my free tutorials on my YouTube channel, Chris' Tutorials. I look forward to helping you grow as a programmer and creator!

Visualizar o perfil completo

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 ao curso: Ei, pessoal, Chris, aqui. E neste vídeo, eu tenho algo muito legal. Estou animado para compartilhar com todos vocês. É meu novo curso de desenvolvimento do GidoGame para criar um jogo semelhante ao de um sobrevivente Então, temos muito conteúdo lá dentro. Quer dizer, são mais de 60 aulas e quase 12 horas de vídeo. De longe, é o curso de desenvolvimento de jogos mais longo e completo que eu já lancei. Então, se você já pensou criar seu próprio jogo divertido Survivors Light, é exatamente isso que vamos fazer Vamos construí-lo passo a passo, do zero. Usaremos a versão 4.4 do GidoEngine, que você provavelmente já sabe que é gratuita e de código aberto Então, vamos codificar tudo no script GD. Que é a linguagem criada especificamente para o editor Gadot É amigável para iniciantes, fácil de ler e totalmente integrado ao motor ado Então, funciona de forma fantástica para fazer protótipos de jogos como esse Então, se você é novato desenvolvimento de jogos ou já programou um pouco e quer realmente solidificar suas habilidades com um novo projeto interessante, acho que este curso será para Começaremos de forma simples, nos familiarizando com o essencial, como a movimentação de personagens de cima para baixo Então, vamos realmente começar a aprimorá-lo, desenvolvendo alguns conceitos genuinamente complexos Você adicionará estatísticas de personagens, sistemas de nivelamento, coleta de itens e até criaremos um sistema de desova que posicionará todos os seus inimigos fora da tela para que eles possam atacar o jogador por todos os lados Então, em poucas palavras, vamos realmente experimentar o sistema de cena Godos two D. Isso abrangerá todo o resto, desde projéteis até a criação de interfaces de usuário sofisticadas Ao final do curso, você terá sobreviventes totalmente jogáveis, como um protótipo de jogo visto em segundo plano e todo o conhecimento necessário para transformá-lo em Então, o que você diz? Você está pronto para transformar essas ideias de jogo em algo real? Venha se juntar a mim no curso e vamos construir algo incrível juntos. 2. Configuração do projeto no Godot: Olá pessoal, Chris aqui, neste vídeo, começaremos com a primeira etapa do nosso projeto Survivors Like e GD Script baixando o GDOEngine Se você ainda não sabe, o Gadot é um mecanismo de jogo gratuito de código aberto que tem sua própria linguagem principal, GD Script, escrito especificamente para o Gdo, que é o que vamos usar para codificar É uma linguagem de script. Você pode, é claro, usar outras linguagens em Deus, como C Sharp, que tem um forte suporte embutido com uma conversão do A maioria dos tutoriais que você encontrará estará em GDScript porque o GD Script é rápido para começar GDScript porque o GD Script é rápido Tem uma integração muito boa com o Editor EUI. É fácil de usar e você não precisa compilar seus scripts toda vez que quiser fazer alterações nele Então, no que diz respeito à simplicidade, especialmente para pequenos projetos, GD Script tem muito a seu favor Então, olhando para o site do Gado, vou usar a versão atual do Gado 4.4 0.1. Especificamente, vou baixar a versão não mono, que significa que não tem suporte para C Sharp porque a versão exclusiva do GD Script permite que você exporte para a web Mas se você usa o Gado Mono, esse recurso não é suportado Então, o Gadot 4.5 já está sendo lançado, e há alguns recursos que eu acho muito legais sendo lançados Mas como estamos tentando manter esse curso para iniciantes de nível intermediário, não quero sobrecarregar ninguém com todos esses conceitos Então, vamos clicar em Baixar e pegar o 4.4 0.1, e queremos a versão azul aqui. Não é Mono. Isso será apenas para GD Script. Se você quiser C sharp, você pode pegar o.net. Não precisaremos disso para esta versão do projeto. Eu poderia criar uma versão C Sharp do curso mais tarde, se fizer sentido. Vamos ver como as coisas vão. Então você vai querer salvar isso instalá-lo e depois abrir o GADOEditor Então, depois de abri-lo, você deve entrar em contato com o gerente de projeto, que lhe dará uma lista dos seus projetos atuais. Você provavelmente não tem muita coisa aqui. Talvez haja algumas demonstrações. Mas o que vamos querer fazer é criar nosso novo projeto. Então, vamos criar um novo projeto, e você pode dar a ele o nome que quiser. Eu vou chamá-lo de script de nome sutil de Survivors, eu sei, porque é um roteiro GD e é um estilo de Então, vou colocar isso no meu diretório de tutoriais, que eu configurei especificamente para esses tipos de tutoriais longos Então, vamos definir isso como a pasta atual, e devemos ver algo como o nome do projeto aqui e o caminho para o projeto completo. Porque eu fiz Script survivors A de uma palavra, na verdade, ele não colocou um separador Então, vou usar apenas um traço como separador padrão para espaços E vamos querer o renderizador no modo móvel. Este é um curso de pixel art, então realmente não precisamos do renderizador Ford por nenhum motivo, e vamos continuar criando com ele Então, depois que seu projeto for inicializado, você deverá ver as três portas de visualização D aqui Uma das coisas legais sobre o Gadot é que ele tem dois fluxos de trabalho completamente separados para dois D e três D, mas suporta os dois Ao contrário do Unity, eles são entidades completamente separadas. Portanto, não é fingir dois D em um sistema de três D. Na verdade, são completamente dois D. E se você olhar para a esquerda nesta janela de cena, você verá que há, na verdade, quatro tipos de nós aqui, duas cenas D, três cenas D, interface de usuário. E então, se clicarmos em outro nó, há a classe base aqui node, que não tem componentes 2d3d Portanto, não é uma posição em nenhum lugar, você a usaria para coisas como sistemas, processamento de informações básicas, não para objetos realmente no mundo do jogo. Para tudo o que está no mundo do jogo, geralmente, usaremos uma cena em dois D. Então, esse será um ícone de nó azul aqui, assim como a diferença. E então a interface do usuário são os nós de controle. Então, isso é marcado em verde, qualquer coisa que seja um botão na tela, texto de combate flutuante, janelas pop-up da interface do usuário, como quando estamos selecionando recompensas pelo que você pode obter ao subir de nível Todos esses são nós de interface de usuário. Então, é claro, à medida que avançamos, explicarei mais sobre o que realmente é um nó. Por enquanto, vamos abordar um pouco mais a interface. Portanto, temos o sistema de arquivos no canto inferior esquerdo. É aí que você terá todos os seus arquivos no Gdo , incluindo todos os ativos importados, seus arquivos SEN, que é onde você pega um ou mais nós e os salva em uma cena, da qual você pode criar cópias de qualquer lugar do jogo Portanto, é basicamente um modelo que você pode reutilizar. E depois outros arquivos Gdo e não Gudo como recursos Então, na janela de exibição aqui, você tem seu acesso X, Y aqui. Um ponto distintivo abaixo é na verdade, a direção positiva do eixo Y. Então, se você está falando sobre subir, você quer ir para Y negativo, e se você quiser se mover para baixo na tela, você estaria falando sobre um valor Y positivo. A direita é X positivo e, em seguida, a esquerda é X negativo. Então, isso será muito relevante quando estivermos movendo nossos personagens pela tela Você quer ter certeza de que eles se movem na direção certa e que você também está recebendo informações para a direção certa. Se você olhar bem de perto o ponto de 1.200 pixels, pelo menos para mim, haverá os limites da nossa interface de usuário Portanto, a interface do usuário geralmente está em sua própria camada de tela separada. Portanto, é uma coisa completamente separada do próprio mundo dos dois jogos D. Você pode pensar na interface de usuário da interface do usuário como uma espécie de camada na parte superior da câmera enquanto visualiza os dois mundos D. Então, sempre que a câmera se move, todos os elementos da interface do usuário também se movem. Mas os objetos do mundo do jogo geralmente não se movem com a câmera. Então, se você mover a câmera, a interface do usuário permanecerá no lugar e tudo abaixo dela, os personagens, os inimigos, aqueles não se moverão com a câmera. E esse é um dos maiores fatores distintivos entre os dois nós D e os nós de controle da interface do usuário Qualquer coisa que seja um elemento de interface do usuário é um nó de controle em Gadot. À direita, temos o inspetor que é usado para definir quaisquer propriedades sobre seus nós Ao escrever scripts, você pode atribuir a ele uma tag at export, que o marca como editável dentro do inspetor Isso é muito importante. Vamos fazer muito disso. Então você vai editar isso aqui. Obviamente, existem outras janelas que têm importância variável Também abordarei isso nos vídeos posteriores. Então, no próximo vídeo, vamos configurar nosso projeto. Importaremos todos os recursos artísticos de que precisamos, incluindo áudio, música, arte e fontes. E também há alguns plug-ins que acho que seriam extremamente úteis para o projeto, os gratuitos para baixar e usar. Então, abordaremos tudo isso no segundo vídeo. 3. Arte, som e plugins ~ Importação e instalação: Então, neste vídeo, continuaremos com a configuração do nosso projeto, configurando todos os ativos, áudio e plug-ins nos projetos que estamos prontos para começar a trabalhar. Então, no PaySpn, tenho todos os links para os recursos de que precisamos para o curso, tudo o que usei no projeto de pré-gravação para sobreviventes do roteiro Então, se você seguir o link aqui no topo, eu vou ampliar isso. Basicamente, você pode acessar cada um desses links e só precisa das versões gratuitas de cada ativo. Eu tenho que compartilhá-lo dessa forma para respeitar a regra de não redistribuição que muitos desses ativos têm, mas você basicamente só precisa seguir os links para cada página da loja e pegar a versão gratuita Então, primeiro, Pixel Crawler tem nosso modelo baseado em personagens que usaremos para configurar algumas armas e inimigos É realmente fundamental para este tutorial, então é nisso que, na verdade, baseamos grande parte do Alpha. Então, a seguir, os ícones da fantasia de Raven. Para elementos de interface do usuário, interface de usuário Crimson Fantasy. A fonte, eu vou usar m5x7. Mas, honestamente, você pode simplesmente escolher qualquer fonte de pixel art que achar boa Também há muita coisa sobre itch dot IO. Para alguns efeitos sonoros básicos de áudio do jogo, Leo oferece RPG Essentials SFX gratuitamente. E então, para a música, The Red Hearts prepared to Dev by Tall Beard é uma música de chip tune absolutamente perfeita para o estilo do jogo Survivors Light. Na verdade, funciona muito, muito bem. Ok, então você baixa todos os arquivos zip e, em seguida, o que você pode fazer é clicar com o botão direito do mouse no sistema de arquivos criar uma nova pasta para arte. Vou colocar todas as imagens aqui. E então clique com o botão direito, crie uma nova pasta para áudio, qualquer coisa que esteja em Efeitos sonoros ou música, eu vou colocar lá. E então, para abri-lo rapidamente no Explorador de Arquivos do Windows, ou o equivalente, se você estiver no Mac ou no Linux, é clicar com o botão direito do mouse e clicar em Abrir e Gerenciador de Arquivos. OK. E então você só quer extrair todos os arquivos para essa pasta de arte. Então, aqui temos a GUI Crimson fantasy, temos os ícones de fantasia e, em seguida, o pacote gratuito Pixel crawler A única exceção é que, para os ícones de fantasia, existem três ou quatro versões diferentes. Eu estava apenas usando as planilhas de sprites completas. É mais fácil trabalhar com eles no Gadot porque você pode criar um recurso de textura de atlas e, em seguida, basta escolher o ícone que deseja selecionar para Para cada um dos itens aos quais você atribuirá um ícone, acho muito mais fácil trabalhar dessa forma Além disso, para Gadot, se estiver importando cada ícone separadamente, o que é uma opção desse pacote, leva muito tempo para realmente ser carregado no motor Então, quando você tem suas imagens compactadas em um arquivo como esse, é muito mais eficiente. Eu acho que é o caminho a percorrer. Além disso, acho que estava apenas trazendo o diretório inteiro. Eu não mudo os nomes dos arquivos nem nada parecido. Normalmente, em Gadot, você usaria letras maiúsculas e minúsculas para os nomes das pastas do seu diretório, mas acho que é mais simples usar o que os artistas forneceram aqui e seguir em frente Portanto, não deve causar problemas nem nada. Talvez um pouco otimizado, mas está tudo bem. E então, para o áudio dos efeitos sonoros, se você abrir o zíper, viremos assim. E a música, eu estava apenas fazendo o box jump de três Red Hearts, que é a primeira faixa musical Na verdade, você pode simplesmente selecionar faixa de música que deseja usar para o seu nível de jogo, mas acho que essa funciona muito, muito bem Sabe, vamos dar uma prévia por um minuto. Sim, então acho que é uma faixa absolutamente matadora para jogos no estilo Survivor Então, depois de importar tudo, você o coloca em seus arquivos. Se você reabrir a janela do Gado, deverá ver tudo o que foi importado para essas pastas corretamente e, em seguida, deverá ser exibido aqui à esquerda Portanto, você pode receber algumas mensagens de erro ao importar coisas pela primeira vez Você pode simplesmente confirmar que os arquivos estão lá, e isso é o mais importante aqui. Acho que essas mensagens podem ser meio que ignoradas. Drop Stable nem tem nada a ver com esse projeto. Pode estar relacionado ao armazenamento em cache no meu computador. Mas o importante é que temos os arquivos aqui. Você pode clicar duas vezes neles. Você pode ver que está sendo reconhecido, como a música lá e os efeitos sonoros aqui. Então parece que estamos bem. Então vá em frente e limpe esse logotipo. Portanto, precisamos de dois plug-ins para o curso. Primeiro, acho que é uma grande qualidade de vida quando você está navegando pelo sistema de arquivos por aqui É chamado de recolher pastas porque você pode perceber que, ao abrir várias pastas como essa, não há uma maneira fácil de recolher ou dobrar todas elas para que você possa ver todo o sistema de arquivos aqui em uma janela. Então, o que você quer fazer é ir até a Asset Lib aqui no topo e depois procurar por colapso Então, clique na barra de pesquisa e digite fechar. E então o que queremos aqui é recolher pastas. Então baixe isso. Instale-o Ok, direi que foi instalado com sucesso. Agora, queremos ir para Projeto no canto superior esquerdo, configurações do projeto e ir para a guia de plug-ins aqui. Marque a opção ativada, clique em Fechar. E o que isso faz é criar esse pequeno ícone aqui, onde você pode recolher tudo e fazer com que todas as pastas voltem para a raiz. Nada foi expandido e é muito mais fácil navegar pelo sistema de arquivos com isso. Acho que é um botão muito útil. Deveria estar lá no básico de Gadot, honestamente. Então, o outro é um plug-in muito mais complexo, e vamos usá-lo para máquinas de estado em Gadot. Também é usado para árvores de comportamento, mas como a IA é muito simples e um jogo de sobrevivência, vamos usar apenas máquinas de estado Não há necessidade de tornar isso mais complexo com uma árvore de comportamento. Então, estamos procurando o Limbo AI e, como estou no 4.4, vou usar o Limbo AI 4.4, é claro Você pode notar que atualmente aqui, pelo menos, ainda não há 4.5 lançado porque, bem, quero dizer, 4.5 ainda está em Dev, então pode funcionar se você decidir usar a versão Dv ou pode ter alguns problemas Provavelmente funcionará, mas, você sabe, pode haver um bug aqui ou ali. Então, você sabe, outro motivo para ficar com a versão estável do Gado. Então, vamos fazer o download disso, e esse será o nosso plug-in de máquina de estado . Nós podemos instalá-lo. Vai demorar um pouco mais porque esse é um plugue bem grande. Vou ignorar essas mensagens mais uma vez. Na verdade, isso pode estar acontecendo porque o nome do projeto é o mesmo, mesmo que o diretório seja diferente, então vou mudar o nome do projeto para que essas coisas parem de aparecer. Espero que isso resolva. Então, vou mudar o nome e dar a ele o nome GD script lá. É uma etiqueta extra? Vamos encerrar que vou limpar as mensagens e recarregar o projeto enquanto estou avançando e vou ver se há algum problema ao recarregar o Não, ok, parece bom. OK. Então, se verificarmos as configurações do projeto e você acessar Plugins, você notará que o Limbo AI não aparece aqui Limbo AI é, na verdade, escrito em C plus plus, então pode ser por isso que ele não aparece especificamente como um plug-in do cado Imagino que ele tenha feito isso para maximizar a eficiência do código, já que o CPlusPlus é mais rápido que o script C Sharp e Mas sim, é assim que é. Então, para confirmar que o Limbo AI funciona, podemos criar rapidamente uma nova cena de TD aqui no canto superior esquerdo E então clique com o botão direito aqui no nó raiz, no nó dois D, adicione um nó filho e procure apenas digitar State. Você deve ver o estado do Limbo aparecer e o estado BT. Desde que você veja essas classes do Limbo AI aparecendo , você sabe que o plug-in está instalado corretamente Então, para recapitular, devemos ter um áudio com nossos efeitos sonoros em cinco pastas aqui, pelo menos uma faixa de áudio E na arte, deveríamos ter interface gráfica de fantasia Crimson, ícones de fantasia de Raven, e eu estou trazendo apenas a pasta completa da planilha de sprites e, em seguida, Pixel Crawler para nosso personagem principal, nossos adereços de fundo e inimigos, meio que o principal recurso artístico da série de cursos, na verdade E depois uma fonte. Então eu trouxe m5x7 como uma fonte TTF de pontos. Acho que outros tipos também podem funcionar, mas provavelmente é melhor usar o mesmo para obter consistência. E então temos complementos, pastas de recolher e Limbo AIA Então, esses devem ser todos os arquivos externos que precisamos trazer para este curso. Todo o resto será um script GD que escrevemos, cenas que configuramos ou outros arquivos Gadot que criamos, como recursos que podem ser salvos em um Então, isso vai ser o fim deste vídeo. Em seguida, vamos começar a criar nossos dois personagens do jogo D de cima para baixo e adicionar alguns controles básicos de movimento ao personagem, que ele possa se mover na tela. 4. Movimento do jogador de cima para baixo: Então, neste tutorial, vamos implementar o movimento do personagem de cima para baixo cena do nosso personagem principal. Mas logo antes de entrarmos nisso, quero ressaltar que podemos excluir a pasta demo do Limbo AI que importa automaticamente com o próprio plug-in Se você quiser assistir à demonstração ou mantê-la lá, fique à vontade. Isso inclui exemplos de como usar o Limbo AI, mas mostrarei em vídeo essas etapas especificamente para a máquina de estado Então, na verdade, não precisamos disso para nosso projeto. Vou remover isso. Ok, e agora estamos prontos para começar. Então, queremos começar com uma cena em dois D no canto superior esquerdo, então vou clicar em criar uma cena D do nó raiz dois. Então, isso nos dará um nó base dois D. Agora, a raiz do nosso personagem, em geral, queremos ser um corpo de personagem dois D, que é um tipo de nó dois D. Então, podemos clicar com o botão direito do mouse no nosso nó dois D e alterar o Tipo, e então digitaremos o caractere. Encontraremos o corpo dois do personagem D. Note que isso herda do corpo físico dois D, que é um objeto de colisão Que é um tipo de nó dois D. Então, há toda uma série de classes ou tipos de objetos o corpo do personagem é herdado, e ele adquire todas as características de todas as classes anteriores Então isso significa que qualquer coisa que um corpo físico dois D possa fazer, um corpo de personagem dois D também pode fazer. Então, vamos clicar em mudar aqui para corpo do personagem dois D. E assim que você fizer isso, haverá um pequeno sinal de aviso triangular amarelo dizendo que o objeto de colisão não tem forma Então, precisamos clicar com o botão direito do mouse e adicionar um nó secundário, que será uma colisão em forma de dois D, e eu vou ampliar o centro de 0,00 Você ainda não verá nada porque, na verdade, não adicionamos um sprite Mas vamos começar clicando na forma e no inspetor do lado direito e fazendo uma nova forma de círculo Então, podemos voltar para editar isso e reduzir seu tamanho, mas primeiro precisamos do sprite para realmente ver com o que estamos trabalhando Então, vamos pegar o nó raiz e também renomeá-lo pressionando F dois E eu vou chamá-lo apenas de player. Você também pode chamá-lo de personagem do jogador ou corpo do personagem do jogador dois D, o que fizer sentido para você. E então vamos salvar essa cena, que é basicamente a cena raiz e qualquer um dos nós secundários em um arquivo, um arquivo de cena TACN com pontos em nosso projeto Então, se pressionarmos Control S para salvar e clicarmos no canto superior direito, isso criará um novo botão de pasta. E vamos dar um nome a ele. Vou usar caracteres, vou usar letras minúsculas, que normalmente é o nome padrão do Gadol, maiúsculas e minúsculas. Então, se você precisar de espaços, você colocaria sublinhado e outras coisas, mais ou menos assim Então, vamos fazer personagens. E então, em personagens, criarei uma pasta para o jogador só porque sei de antemão que haverá vários scripts e, em de antemão que haverá vários scripts e, seguida, podemos combiná-los todos no mesmo subdiretório Então, vou criar uma nova pasta. Jogador. E digamos Ok. Então, temos o player dot TSC e vamos salvá-lo nesse diretório ou pasta Então salve a cena lá. Então, em Godot, seu projeto é essencialmente composto de cenas dentro de cenas Então você pode ter uma cena de jogo principal. Temos toda a configuração do sistema e, abaixo dela, você pode carregar a cena mundial do jogo, que é o mapa de dois D e os objetos que devem ser preenchidos e, dentro desses dois mundos D, você teria, é claro, a cena do seu jogador, as cenas de seus inimigos, seus orcs, seus esqueletos, etc Então, quando sua cena é salva em um arquivo, é muito fácil instanciar isso porque basicamente será pegar os dados salvos, carregar uma cópia deles e colocá-la em sua Então, muito rapidamente, eu pude realmente demonstrar isso. Se clicarmos nessa nova guia, crie um novo botão de cena. Podemos adicionar uma nova cena em dois D aqui. Vamos chamar isso de mundo. Então, vou pressionar F dois para renomeá-lo, e isso será apenas um mundo Podemos mantê-lo como um nó padrão dois D. Na verdade, não precisamos que ele tenha outra posição além uma posição na tela. Então, vamos pressionar Control S para salvar essa cena. Vou até a raiz e podemos salvar o World Dot TSN dentro daqui Ok, agora queremos adicionar uma cópia do nosso player ao mundo. Então, o que podemos fazer é arrastar a cena do jogador para a hierarquia mundial na guia de cena no canto superior esquerdo Então, basta arrastar o player dot TSN até aqui em World. E agora há uma cópia do jogador dentro do mundo do jogo. Então você sabe que está lá porque você pode passar o mouse sobre ele. Eu vou dizer jogador aqui. Você pode ver o ícone do corpo do personagem dois D e ver a forma de colisão que definimos Agora, ainda não há nenhum sprite. Vamos adicionar isso agora. Então, vou clicar em Controlar-nos para salvar o mundo. Vamos até o jogador. Vou clicar com o botão direito do mouse no player, adicionar um nó secundário que estamos procurando por sprite Então Sprite two D. Há também um nó Sprite two D animado, e ambos podem ser usados praticamente para os mesmos propósitos Eles configuraram as coisas de forma um pouco diferente. Eu diria que, para personagens de jogadores, é realmente mais fácil trabalhar com Sprite two D e depois definir as propriedades que você precisa para animar no reprodutor de animação Falaremos mais sobre a animação de um sprite no próximo vídeo Então, vamos adicionar um nó Sprite two D. E, por enquanto, vamos querer carregar uma textura. Quando estamos carregando a textura aqui, não vamos definir uma única imagem de sprite Na verdade, vamos definir uma folha de sprites. Então, obtemos nossa folha de sprites do diretório de arte. No pacote Pixel Crawler, creio que foram entidades, personagens, corpo A e animações Então, vamos começar com o ídolo. Então, para esse personagem, você tem uma folha de sprite com o lado negativo e Quando você está jogando dois jogos D de cima para baixo, você pode simplesmente virar a folha lateral do sprite Da esquerda para a direita, o que significa que você não precisa criar uma quarta planilha de sprites para a esquerda e direita, pois você pode simplesmente reutilizar a mesma planilha de sprites e ela também funciona Você economiza muito tempo para animá-lo dessa forma. Então, queremos que o Idle down comece apenas para que possamos realmente ver o personagem que estamos vendo Então, vamos carregar isso aqui. Portanto, esse é um sprite de personagem básico. Portanto, a ideia aqui é que você possa adicionar roupas como um sprite adicional em cima delas, fazer qualquer personalização, mas as animações básicas permaneçam as mesmas, pois você desenvolveria o personagem final com estilos basicamente diferentes OK, então algumas coisas provavelmente se destacam. Primeiramente, o personagem obviamente não tem roupas. Portanto, esse é um sprite de personagem básico. A ideia é que o que você faria seria pegar sprites de roupas adicionais e adicioná-los à animação base para o personagem final, talvez como um chapéu de mago ou algo parecido E a ideia é que você possa trocar sprites para finalizar seu personagem final Mas para as animações básicas, elas são fornecidas aqui no pacote gratuito, e você simplesmente criaria a partir daí Então, vamos trabalhar com isso para o tutorial. Os outros dois problemas óbvios são, bem, um temos quatro cópias do personagem aparecendo na tela ao mesmo tempo. Então, queremos fazer com que apenas um show. E a maneira de fazer isso é ir até a guia de animação aqui e alterar os quadros H para o número de sprites que estão sendo exibidos nessa folha de sprites horizontal Então, eu apenas mudo os quadros H para quatro. E agora está mostrando apenas a posição zero do quadro, que é o primeiro sprite nessa animação inativa O terceiro problema é que está muito embaçado para a arte em pixels Portanto, podemos corrigir isso em todo o nosso projeto acessando as configurações do projeto e queremos rolar para baixo até, acredito que seja um renderizador Não, texturas. Portanto, renderizar e depois texturizar o filtro de textura linear padrão aqui é mais apropriado se você estiver fazendo, eu acho, coisas como arte vetorial Mas para pixel art, que precisa ser Pixel Perfect, você deseja alterar isso para o mais próximo. E assim que você fizer isso, ele mostrará basicamente cada pixel renderizado de forma nítida, como seria de esperar de um jogo de pixel art E basicamente para o projeto, isso é tudo que você precisará fazer para configurá-lo especificamente para um formato de pixel art. Agora, o personagem e a forma da colisão estão um pouco estranhos aqui agora Geralmente, para jogos de cima para baixo, você quer que a forma de colisão fique em algum lugar ao redor dos pés do personagem Então, eu gosto de manter minhas cenas ainda centradas em 00 para que eu saiba basicamente a posição exata em que o personagem está representado no mundo do jogo e o deslocamento não seja estranho ou algo parecido Então, o que realmente queremos fazer aqui é compensar, não a cena base Queremos manter isso em zero, zero, mas no nó do sprite Então, se você selecionar o Sprite dois D e pressionar W para ir para o modo de movimento, você pode clicar com o botão esquerdo, segurar e arrastá-lo para cima Se você quiser encaixá-lo eixo Y, mantenha a tecla Shift pressionada, que ajuda a evitar que ela vá para a esquerda, a menos que você vá muito longe E só queremos arrastar isso até que os pés do personagem estejam basicamente ali. E então queremos que a forma de colisão seja uma representação da área dos pés do personagem, porque é aqui o personagem poderia colidir com outros objetos Portanto, faz sentido que a posição seja onde os personagens realmente estão no mundo dos dois jogos D. Hum, para se acostumar com a perspectiva de dois D leva um pouco de tempo para se acostumar, porque é um pouco menos óbvio, eu acho, do que três D, onde seria mais parecido com a vida real. Então, aqui só temos que dar a ilusão de que nossos personagens realmente estão ali, mesmo que o personagem vá daqui até aqui, essa é a área em que o personagem está o personagem está Então, podemos salvar isso aí. Isso deve ser bom. Apenas para referência, eram 4,12 pixels Na verdade, vou arredondar isso para quatro, um pouco de preferência para tentar manter tudo em tamanhos perfeitos em pixels. Para um jogo de arte Pix, provavelmente não será um grande problema e causará problemas, mas, você sabe, por precaução Então, agora, se voltarmos para nossa cena mundial, veremos que nosso personagem está realmente no mundo do jogo. E se quisermos jogar o mundo, apertaríamos este botão play aqui, que reproduz a cena atual do mundo. E poderemos ver o personagem muito, muito pequeno no canto superior esquerdo. Na verdade, é quase impossível ver isso. Então, a próxima coisa que provavelmente queremos é adicionar uma câmera. Então, vamos clicar com o botão direito do mouse no mundo, adicionar um nó secundário, fazer duas câmeras D. E embora o mundo crie automaticamente uma câmera padrão, mesmo quando você não adicionou um nó de câmera, quando você define corretamente uma câmera, você pode definir o Zoom, que é muito útil para a Pixart porque estamos falando sobre trabalhar com caracteres de 48 pixels por 32 pixels, algo assim assim. Então, queremos pegar o Zoom e provavelmente aumentá-lo para cerca de três ou quatro, podemos ver que a câmera 2 D agora também está centralizada no ponto zero, em vez de ser mais uma caixa de tela padrão aqui Na verdade, podemos ver que a câmera é essa linha rosa. E se rodarmos a cena agora, nosso personagem deve estar centralizado muito maior e mais visível Então, se você quiser, você pode aumentar isso para quatro. Acho que três é muito bom por enquanto. Vou mudá-lo mais tarde, se precisarmos. Mas desde que você possa ver o personagem, acho que você é bom. Outra coisa, quando estamos jogando o jogo, acho que quero que isso seja muito mais visível. Então, vamos aumentar o tamanho da janela agora para que possamos projetar uma tela maior de forma mais adequada para que, você sabe, quando estivermos fazendo nossas visualizações, vocês possam realmente ver o que está acontecendo melhor Então, vamos às configurações do projeto, e eu vou pegar a vitrine e mudar isso para algo muito maior. Então eu acho que algo como 1980 por 180 seria bom. Quero dizer, isso depende de qual é a resolução da tela. Para mim, isso vai ser mais ou menos assim. Ok, vou tentar isso na minha tela. Estou trabalhando em um monitor branco extra bem grande aqui, então, um pouco de tentativa e erro. Acho que vai funcionar bem porque ainda consigo ver o botão uh Of aqui. Então, reproduza a cena principal, pause e interrompa os botões atuais do projeto em execução, a propósito Eu diria que, desde que você possa ver isso, tudo bem. Então, com nosso jogo Canvas, desse tamanho, eu provavelmente também quero aumentar o Zoom. Na verdade, você pode editar as propriedades enquanto os jogos são executados. Então, posso simplesmente pegar esse Zoom e alterá-lo para quatro. Vamos tocar novamente e você verá que o tamanho foi atualizado imediatamente. Então, se for grande o suficiente para você, você pode ficar com isso ou podemos ir até cinco. Você sabe, talvez eu realmente faça um zoom 5.0 lá. Agora, no momento, vocês estavam realmente esperando por isso. Vamos entrar no código real. Então, precisamos criar um script que estenda o corpo do personagem em dois D e anexá-lo ao jogador. Podemos fazer tudo isso de uma só vez clicando no botão esquerdo do jogador e depois clicando em anexar um script novo ou existente ao nó selecionado. E vamos chamar isso de script player dot gd E, na verdade, não vamos usar o script básico de movimento D do corpo do personagem modelo. Ou seja, se eu me lembro mais sobre jogos de plataforma, porque isso adiciona salto e, honestamente, podemos escrevê-lo Então, vamos clicar em Criar, e isso nos levará ao editor de scripts aqui. Então, por enquanto, vou mantê-lo como editor de script incorporado. Mas você também pode clicar nesse botão aqui e fazê-lo flutuar se quiser usar o editor de scripts em tela cheia, o que pode ser útil se você realmente gosta de codificação em GD Script Mas aqui, esse script será bem rápido e simples, então não é necessário, na verdade. Então, vamos até o topo. Ok, então podemos ver que nosso script estende o corpo do personagem dois D. Isso significa que nosso script tem a classe base do corpo do personagem dois D. Ok, então se passarmos o mouse sobre o corpo do personagem estendido dois D, você pode ver a hierarquia de classes aqui descendo do corpo do personagem dois D, até o objeto base do Gadot Isso significa apenas que , ao longo do caminho, ele herdará as habilidades de cada uma dessas classes diferentes Então, um TD corporal de personagem , na verdade, pode fazer muita coisa. Nós só vamos precisar de um pouco disso, na verdade. Portanto, lembre-se de que tudo o que está listado lá, cada uma dessas classes, quais você pode entrar clicando nas quais você pode entrar clicando nos nomes delas se quiser ler sobre elas, é algo que o personagem body two D também pode fazer. Então, ler tudo isso seria muita documentação no momento, é bom saber sobre ela. É bom ler à medida que você avança, mas um pouco cansativo por enquanto Então, vamos trabalhar em nossa aula. Queremos dar a ele um nome de classe para que esse script possa ser facilmente referenciado a partir de outros scripts pelo nome, indo até o início da linha E, em seguida, pressione Enter. Vamos até a primeira linha e digitar o nome da classe player. E agora, definimos esse script como o script dos jogadores. Então, este é basicamente um símbolo global Agora, em nosso projeto, podemos pesquisar e usar apenas referenciando player digitado exatamente assim com À medida que avançamos no curso, você verá que isso é extremamente útil, especialmente para algo como o script de um jogador, que muitas outras classes precisarão abordar. Então, vamos trabalhar na função do processo físico do personagem. Então, vamos digitar FU NC para a função e depois sublinhar. E você verá esse menu ser preenchido automaticamente com os métodos definidos dentro das classes principais Essas são basicamente funções que podemos substituir e adicionar no código para que ele realmente faça alguma coisa ou mude o que a classe base fez originalmente Então, queremos o processo de física aqui. Se você encontrar o processo físico e pressionar Enter, ele nos dará a definição completa da função aqui para o nome aqui, processo físico de sublinhado Ok, então aqui temos o nome da nossa função. O sublinhado aqui indica que ele deve ser privado e não acessado por outros scripts e apenas ser acessado por outros scripts e apenas contido ou encapsulado de dentro desse O Delta aqui é o nome do nosso parâmetro e float é o tipo do nosso parâmetro No script GD, você não precisa realmente digitar suas funções Então, se você quiser, pode remover essa flutuação do cólon e chamá-la de Delta Agora, o que é Delta? Bem, isso acabaria sendo o que a coleira decidisse passar para essa função, que, nesse caso, basicamente não tem nada que a impeça de ser outra coisa senão uma bóia Você provavelmente esperaria que fosse um carro alegórico. Portanto, nesse caso, é muito melhor declarar seu tipo com dois pontos e depois flutuar Então, eu recomendo isso. E aqui também está um componente opcional da declaração da função. Temos essa seta, que é um traço ao lado da tecla zero. Ok, e aqui à direita, temos a seta de retorno apontando para o tipo de vazio de retorno Vazio significa que não tem retorno. Você não espera que ele realmente retorne nada que você usaria dentro de outras funções. Então, para digitar isso manualmente, você digitaria um hífen e depois uma nota e assinaria E essa é sua seta de retorno apontando para o tipo de retorno. Ok, então, é claro, quando digitamos isso, nossa função na verdade não tem nada nela. Você pode fazer com que uma função não faça nada digitando passe em minúsculas, então essa é uma palavra-chave reservada Mas sem isso, se eu desfizer isso, você verá esse erro aparecer na parte inferior aqui dizendo bloco final esperado após a declaração da função, significa que deve haver algo aqui depois que a função E você pode expandir essa lista aqui para ver todos os erros dentro do seu script atual, uma pequena janela bem útil Ótimo, se você precisar copiar e colar, basta selecionar tudo e copiar. E você pode colar isso em qualquer outro aplicativo que estiver usando. Talvez você esteja fazendo um relatório de bug ou algo parecido. Ok, então, finalmente, podemos realmente começar a escrever algum código de função. Sei que estou indo um pouco devagar, tentar mantê-lo acessível aqui, especialmente nos vídeos anteriores, com certeza ficará muito mais intenso à medida que o curso avança. Então, primeiro, para nosso processo de física, queremos que o personagem se mova, que significa que precisamos de uma velocidade e uma direção na qual o personagem se mova. Então, em algum lugar, precisamos declarar a rapidez com que nosso personagem se move Então, poderíamos declará-lo diretamente na função. Mas, na verdade, o que eu quero fazer agora é criar uma variável de exportação em que possamos alterar a velocidade no editor com muita facilidade simplesmente indo até aqui à direita e digitando a velocidade que quisermos. E também podemos mudar isso durante o jogo. Então, vamos digitar na velocidade Export var e definir o tipo de flutuação Então, vamos analisar isso lentamente primeiro. Em Exportar, aqui está uma palavra-chave que a declara que pode ser editada no inspetor Ok, e então var aqui significa variável. Velocidade é o nome da variável. Dois pontos aqui definem o tipo e, em seguida, float é o Então, podemos pegar essa velocidade. Na verdade, vamos escrever o passe aqui para o processo de física e, em seguida, pressionar Control para salvá-lo. E você verá a velocidade aparecer aqui e no canto superior direito do script do player Certifique-se de ter selecionado o nó do jogador e você poderá ver isso. Agora, você também pode ver que o padrão é 0,0. Então esse é o valor padrão para float. Você provavelmente quer agilizar, na verdade, atribuir um número real a isso. Então, vou pegar isso e dizer igual, vamos usar 100,0, pressione Control S. Agora o valor padrão é carregado aqui automaticamente porque não definimos um Se você definir um valor personalizado clicando aqui, digamos 150 e pressione Enter agora, a velocidade é 150. Se alterarmos o padrão para 200 aqui e clicarmos em Salvar dentro do script , você verá que o valor personalizado ainda substitui o padrão de Eu posso apertar o botão de reset aqui para redefini-lo para o padrão, então agora é 200. Agora eu quero que a velocidade do script seja 100. Acredito que era isso que eu tinha para o projeto padrão. Sempre podemos mudar isso mais tarde e ficar à vontade para realmente definir velocidade de seus jogadores para qualquer coisa com a qual você se sinta confortável. Isso é completamente. E é assim que podemos fazer com que nossa propriedade definida pelo editor seja usada dentro do script. Portanto, as variáveis de exportação são realmente úteis para torná-las mais acessíveis para editar os detalhes de como nosso script seria editado sem precisar saber nada sobre como o código realmente funciona Ok, então temos nossa velocidade. Podemos escrever o processo de física agora. Ok, então vamos ver aqui. Eu vou primeiro obter a direção de entrada. Ok, então, por enquanto, queremos declarar uma variável de direção, então, var direction E você verá que estou digitando isso dentro da função Então, isso a torna uma variável local para a função, ou seja, assim que as funções forem concluídas, isso será apagado Ele só é usado dentro da função, a menos que retornemos como nosso tipo de retorno. Então, é temporário, basicamente. E vamos definir isso igual à entrada. Agora saiba que estou colocando o I em maiúscula porque esse é um nome de classe ao qual estamos referenciando Portanto, a classe de entrada é que você pode pensar nela como uma classe global. Você pode acessá-los em qualquer lugar se precisar que eles façam algo por você. E vamos usar a classe Import para obter um vetor. Então, um vetor terá componentes X e Y, em vez disso, um vetor dois. Também há o vetor três para três jogos D, que adiciona o eixo Z. Mas para dois jogos D, você só tem X e Y, o que, ao remover o terceiro eixo, torna dois jogos D um pouco mais simples de entender e trabalhar Então, queremos obter o X negativo aqui. Você pode ver os parâmetros que essa função está definindo e, na verdade, há alguns extras aqui, como zona morta, dos quais não precisamos. Mas os quatro que precisamos são X negativo, X positivo, Y negativo e Y positivo. Então, em um dos dois vídeos anteriores, acredito que toquei nisso, mas o X negativo e Gadot permanecem na Então, queremos entrada para a esquerda. Agora, você pode vê-lo sendo preenchido com alguns nomes de cadeia de ação predefinidos Você sabe, é um nome de string, a propósito, porque tem um e comercial aqui na frente da string, que são aspas, e então o nome real aqui, terminando Mas todas essas são ações de interface de usuário padrão, e não é uma boa ideia realmente usá-las. No sentido de controlar seu personagem, porque ele já controla a interface do usuário por padrão. Então, vamos até as configurações do projeto. Então, projete as configurações do projeto no canto superior esquerdo, no mapa de entrada, e digitamos uma nova ação. Vou digitar à esquerda e clicar em Adicionar. Então, nossa ação à esquerda, vou clicar em Adicionar evento aqui e gosto de usar as teclas WASD É bastante normal para muitos jogos. Então, vou apenas digitar A aqui onde diz ouvir a entrada e uma regra. Atribua-o automaticamente à chave A, física ou Unicode Então, basicamente, A no seu teclado. Você pode clicar em OK agora. E agora, mover para a esquerda é atribuído a A. E queremos fazer isso para cima para baixo e para a direita também. Então digite à direita, adicione e, em seguida, clicamos aqui para atribuir a tecla, adicionar evento e pressionar D para a direita. Clique em OK. Agora vamos colocar. Clique em adicionar evento, pressione W para cima, adicione uma ação, para baixo, clique em Adicionar evento, S para baixo e aí está nossa entrada de movimento. Portanto, o Kidob manipulará automaticamente a conversão dessas teclas pressionadas na ação real que podemos usar dentro da coluna de função vetorial G da classe de entrada Então, o que queremos fazer aqui é colocar os nomes das ações que acabamos de digitar Então, podemos fazer a cotação deixada aqui. E você verá que, na verdade, é preenchido automaticamente, e você pode simplesmente pressionar Enter aqui para confirmar que é negativo X para X positivo, certo Você também pode ver aqui que ele meio que apareceu, então podemos clicar duas vezes nele. Em seguida, o terceiro menos Y, podemos digitar ou encontrá-lo na lista. Então, para baixo. E então, para Y positivo, oh, eu realmente misturei isso. O Y negativo está para cima, o positivo Y está para baixo. Então, vou adicionar Y positivo aqui embaixo, e depois aqui, vou simplesmente apagar o valor para baixo e digitar para cima Então, tenho certeza de que está aí. Definitivamente descobriremos em um minuto quando jogarmos o teste. Queremos tomar a direção de entrada e, se não for zero, queremos nos mover. Então, se for zero, só queremos parar de mover nosso personagem por completo Então você pode fazer isso dizendo se é direção. Então, isso basicamente já verifica se a direção é igual ao vetor zero ou não. Então, se a direção significa que não é zero, então podemos pegar a velocidade do nosso personagem Agora, onde obtivemos a propriedade da velocidade? Bem, nosso clássico representa o corpo do personagem dois D, e a velocidade é uma propriedade do corpo do personagem dois D. Então, se eu clicar com o botão direito do mouse no corpo do personagem dois D e ir para o símbolo de pesquisa, posso rolar até aqui e ver a velocidade aparecer aqui na lista Portanto, quaisquer propriedades ou métodos, que são uma função dentro de uma classe que pertence a uma classe mãe, serão herdados e utilizáveis por essa classe herdeira Então, dentro de um jogador, podemos pegar a velocidade e definir isso para que queiramos a direção multiplicada pela velocidade Agora, você verá esse componente Delta aqui. Esse é o tempo entre os quadros. Não precisamos atribuí-lo aqui ao estilo de movimento específico que estamos usando, que é mover e deslizar. Há outro movimento e colisão, onde você passaria e o Delta ao chamar essa função, se bem me lembro Portanto, é um pouco estranho que, você sabe, o Delta seja automaticamente contabilizado aqui, mas é assim que funciona Portanto, qualquer tecla pressionada para movimento é pressionada. Vamos atribuir a velocidade à direção multiplicada pela velocidade Depois disso, aqui embaixo, podemos nos mover e deslizar. Agora, o que aconteceria agora? Na verdade, seria mais fácil mostrar. Vamos clicar em play e ainda não selecionamos uma cena principal. Então, vamos selecionar a cena mundial como nossa cena principal. Vou apenas subir os diretórios aqui e escolher o mundo. Clique duas vezes. Nós temos um personagem. E se eu pressionar uma tecla de movimento e soltar, você verá que isso não impede nosso personagem. Ele meio que continuará deslizando, que poderia ser usado para algum tipo de mecânico de iluminação Mas, para movimentos regulares, na verdade, queremos adicionar uma declaração se aqui como acompanhamento do nosso I. Então, veja e, em seguida, certifique-se de colocar o cólon no final Então, isso basicamente declara o que vem a seguir como um bloco para a função continuar executando E queremos medir a velocidade. Queremos reduzir isso para Serrel. A velocidade é igual ao vetor dois. Então, na verdade, estamos criando um novo vetor dois aqui e colocamos parênteses Você pode ver que o terceiro tipo de construção de um vetor tem um valor X e um Y. Então, dentro dos parênteses, pressione Enter. Então, isso vai separar o primeiro parêntese do segundo e deixar bem claro digitar a lógica X aqui e depois a lógica Y logo abaixo dela Então, queremos nos mover em direção ao ponto de velocidade x a zero. E vamos fazer isso com a velocidade atual. Então, isso basicamente significa que, assim que soltarmos, baixaremos a velocidade para zero imediatamente Há muitas maneiras diferentes de fazer isso. Você pode fazer com que diminua gradualmente com o tempo se usar uma função larp. Mas isso é provavelmente o mais simples. Então, vamos continuar com isso. Vá em direção a. E então, na segunda linha aqui, queremos obter o valor Y para a nova velocidade Então, vá em direção ao ponto Y da velocidade atual, estamos fazendo com que ele se aproxime de zero na mudança ou Delta da velocidade Então, salvamos isso aí, e isso significa que isso vai levar nossa velocidade atual, que pode ser, digamos, a direita em velocidade máxima, para a direita em velocidade máxima, e vamos reduzi-la na quantidade total de velocidade, o que significa que ela cairá imediatamente para zero. Estamos nos aproximando de zero Então, assim que soltamos nossas teclas de entrada, nosso personagem para de se mover, é o resultado final de. Na verdade, conte isso. Então, para declarar um comentário, se você quiser fazer isso, coloque uma hashtag e depois a descrição Assim, você pode manter seus comentários embutidos, se quiser, em geral Atualmente, eu os puxo para o topo da função desta forma, então Controle X e depois Controle V para colá-los. E se você quiser que esse texto apareça na documentação gerada automaticamente para sua turma , você pode fazer dois anúncios comerciais. E salve-o e, em seguida , ele será adicionado à documentação da classe do jogador. E podemos acessar essa documentação clicando em Pesquisar ajuda aqui Procuramos por player, nossa classe personalizada, clicamos em abrir e você pode ver o nome de nossas propriedades, que neste caso se refere apenas a uma variável que existe como parte da classe local. Nesse caso, poderíamos nos referir apenas a uma variável que é um estado local existente dentro da classe em vez de uma variável local de uma função. Assim, você pode editá-los e lê-los conforme necessário. Em outras linguagens de programação, coisas como campos ou propriedades são definidas com muito mais clareza. Mas acho que geralmente para a maioria das funções básicas do GD Script, sua propriedade e variável acabam sendo a mesma coisa Você não declararia algo como um campo privado de apoio, como faria em C Eu diria que na maioria dos casos, porém, porque, você sabe, ainda haveria algumas razões para fazer isso para ter um apoio privado à sua propriedade pública Aqui você pode ver o método aqui e, se rolarmos para baixo, as descrições do método. Então, processo de física. Assim que soltamos nossas teclas de movimento, nosso personagem para de se mover. Então, essa é, na verdade, uma das coisas mais legais sobre o script GD é que ele é essencialmente gerador de autodocumentação Contanto que você coloque os comentários onde eles deveriam estar com os dois e comerciais, você pode comentar um campo ou uma propriedade Você pode comentar um método. E isso é muito útil. Isso torna mais fácil para outras pessoas entenderem basicamente seu código sem ler o script inteiro de cima para baixo. Então, você pode realmente fazer a mesma coisa com velocidade aqui. Então, dois e comerciais e digamos o movimento básico, a base, a velocidade básica de movimento do personagem do jogador Controle S salve, e então você pode ver nossa documentação ainda está aberta aqui na janela do script. Então, se eu clicar no Player, você pode ver, oh, agora, nossa propriedade de velocidade tem uma descrição que pode ser facilmente lida. Então, isso é muito útil. Tenha isso em mente. E agora podemos seguir em frente e clicar em Play. Então, vamos mover nosso personagem WASD. Agora veremos que, assim que pararmos de importar, o personagem para de se mover. que é mais o que você esperaria de um personagem movendo-se em qualquer coisa padrão, como grama, pedra ou qualquer outra coisa, coisas que deveriam ter atrito, não gelo E esse é o movimento básico usaremos no resto do jogo, basicamente. Agora, obviamente, os personagens não são animados. Não temos as animações de execução. Ainda não está voltado para a direção que deveria. Essas são todas as coisas que abordaremos em vídeos futuros. Uma última coisa que quero acrescentar a uma última coisa que quero acrescentar para esse personagem, bem, estamos à frente das coisas, é adicionar apenas mais uma propriedade de nome de exibição. Então, na verdade, vou adicionar uma exportação para uma var, um nome de exibição. E esse será um nome de string de tipo. E vamos definir isso como igual ao ampersan, seja qual for o padrão que você quiser, basta torná-lo player e apertar Portanto, para nosso player, podemos ver que agora a propriedade do nome de exibição do nome da string é editável dentro do inspetor Então, vou mudar isso e configurá-lo para Jaco, porque vamos fazer com que nosso personagem, por padrão, tenha uma arma de lança Então eu acho que isso funciona. Nos jogos Survivor Light, geralmente, você teria vários personagens para escolher Portanto, fazer com que todos tenham um nome de exibição distinto faz sentido. Agora, rápido, também há uma propriedade de nome que todos os nós têm. Isso se refere ao nome do nó aqui em cima. Mas você pode ver coisas como a forma de colisão em dois D. Você não transfere espaços e nomes de nós Então, usar isso como seu nome de exibição pode ser um pouco estranho exemplo, digamos que você adicione uma subclasse como Fire Dragoon Mas você pode criar o nome do nó do jogador aqui, Freragoon, sem esse espaço, para que você possa ter um nome de exibição distinto e separado por ter uma propriedade personalizada como Então, o que é isso para o dragão? Pressione Control S. E isso parece aceitável no momento. Eventualmente, pegaremos essa entrada e a moveremos para um script separado. Usaremos estatísticas como a velocidade do personagem e também faremos disso um script separado. Mas isso é um bom começo. Então, isso vai ser o fim deste vídeo. Eu tentei desacelerar aqui intencionalmente para cobrir toda a terminologia do script que vamos usar para o script GD como, você sabe, a base para o resto do curso Todas essas são coisas que continuarão surgindo repetidamente Espero que não tenha sido muito lento para ninguém, mas vamos acelerar a partir daqui Então, até o próximo vídeo, eu os verei. 5. Reproduzir animações a partir de Spritesheets: Então, do jeito que as coisas estão agora, nosso personagem pode se mover tecnicamente, mas não há animação alguma no sprite Então, queremos que nosso personagem anime quando ele dirige ídolos e, claro, a animação da morte também quando perdemos o jogo Ok, então a primeira coisa que vamos fazer é realmente mudar a planilha de sprites aqui Se você procurar no pacote Pixel Crawler, podemos pegar o lençol de sprites do Idol para a noite, ou você pode usar o ladino ou o mago Então eu vou pegar isso e trazê-lo aqui. E esses são basicamente sprites voltados para o lado. Você notará que esse personagem não tem altos nem baixos. No entanto, algumas vantagens disso. Primeiro, se você está animando apenas uma direção e depois invertendo-a, que é o que o sobrevivente padrão realmente faz que é o que o sobrevivente padrão realmente É muito mais fácil criar personagens porque você só precisa animar uma direção E em segundo lugar, você pode pular completamente as árvores de animação e se concentrar apenas em um reprodutor de animação e uma máquina de estado que controla a lógica seu personagem alternar entre estados como Idle. Por esses motivos, na verdade, vamos passar para a planilha noturna de sprites do Idol Você poderia usar o ídolo praticamente de forma intercambiável. Posteriormente, você poderia usar, tipo, a folha de sprites desonestos, como ali mesmo, ou a do mago aqui também Então, qualquer um deles funcionará perfeitamente bem, e já existe a configuração para ter três classes de personagens ali mesmo. Mas, para começar, era mais um cavaleiro empunhando uma lança cavaleiro empunhando Então, como um personagem chamado Agron, esse espírito meio que se encaixa, e ele será capaz de ele será capaz Ok, então temos nossa folha de sprites definida aqui. Queremos transformar isso em uma animação ociosa. Os quadros He já foram configurados aqui, mas precisamos de um reprodutor de animação real para fazer isso. Então, clique com o botão direito do mouse no nó do jogador e adicione um nó filho. Procure um reprodutor de animação. Adicione isso. Então, quando você tiver o reprodutor de animação, a janela de animação estará aqui na parte inferior. Você pode clicar aqui se ainda precisar. E queremos ir para a animação e depois para Nu e digitar o nome da animação. Então, estamos começando com a animação ociosa, então vamos digitar Idle E podemos adicionar uma trilha de propriedades. Então, vamos pegar do Sprite two D algumas dessas propriedades, ou seja, a textura. Então, clique duas vezes nele. Vamos clicar com o botão direito do mouse em Property Track, adicionar os quadros H e, em seguida, na propriedade Track, Sprite, dois quadros D. V. Por fim, por enquanto, pelo menos precisamos do número do quadro em si. Portanto, adicione e enquadre como uma propriedade. Então, agora podemos pegar esse Zoom e ampliar um pouco nossa planilha de sprites Primeiro, quero pegar o tempo de captura aqui, onde diz 0,033 3 segundos, e alterá-lo para 0,1, que significa que trabalharemos em intervalos de 0,1 segundo ou um décimo Em seguida, habilite esse encaixe no cursor da linha do tempo. Agora você poderá simplesmente clicar aqui nos intervalos de 0,1 segundo, facilitando muito o trabalho com Você deve ter visto nesta folha brilhante que há quatro quadros de animação. Então, vamos percorrê-los a cada 0,1 segundo, o que significa quatro vezes 0,1, queremos uma animação de 0,4 segundo. Então, aqui no lado direito, digite 0,4 e, em seguida, essa coisa que parece flechas se alimentando Loop de animação, você quer clicar nele para fazer nosso loop de animação Agora, em nossa linha do tempo de animação, não há quadros-chave. Definitivamente, queremos definir um quadro-chave no início da animação para todas essas propriedades Então clique com o botão direito do mouse na chave de inserção Se você clicar com o botão esquerdo aqui, verá que o valor da textura já está predefinido para essa animação noturna ociosa Se não estiver, convém alterá-la para a planilha de sprites Idle A partir daqui, você pode arrastar e soltar assim e colocar isso lá. Então, o que esse quadro-chave significa é que, no início de nossa animação, em 0,0 segundos, quando a animação começar a ser reproduzida, ele definirá a textura do nosso sprite com esse valor, o que significa que, assim que a animação começar, trocamos a planilha do sprite Agora, quadros H, também queremos clicar com o botão direito do mouse e pressionar a tecla Serta. Agora, já predefinimos nosso valor aqui como quatro nesses dois brilhantes D. Então você pode ver que, ao digitar a tecla Serta, ela adicionará qualquer valor definido atualmente como o ponto do quadro-chave na linha do tempo da animação E sempre que esses quadros-chave aparecem, isso significa que o valor naquele momento é esse valor Agora, para nosso jogo de arte Pix, quase sempre usaremos o modo discreto aqui na extrema direita Você pode ver esses três pontos. O que isso significa é que o valor não muda até atingir o ponto do quadro-chave. Em algo mais parecido com um jogo em três D, você pode fazer uma animação contínua, o que significa que ela gradualmente alternará entre os valores dos quadros-chave Portanto, se você tivesse algo como um quadro-chave de posição , ele animaria a posição entre a posição inicial de zero e a posição final de 100 ao longo do tempo à medida que a linha do tempo da animação progride Portanto, muitas animações em jogos estão, na verdade, apenas alterando os valores das propriedades do seu objeto com o passar do tempo. Ok, então continuando com os quadros em V, podemos clicar com o botão direito do mouse para inserir uma chave. Você verá que o valor aqui, se clicarmos com o botão esquerdo no quadro-chave, já está definido como um. É isso que queremos. Mais uma vez, se olharmos para a planilha de sprites do Idol, ela tem quatro quadros H, quadros horizontais e um quadro vertical em termos de linhas e colunas É por isso que temos quatro para quadros H e um para quadro V. Não precisamos fazer muita personalização aqui. Só precisamos garantir que, no início, ele esteja definido com esses valores para que nossa animação seja reproduzida corretamente. Agora, o que realmente precisamos fazer é colocar nossos quatro quadros de animação aqui. Então, clique com o botão direito no primeiro quadro e pressione a tecla Inserir. Você verá que, no quadro, ele realmente mostra uma prévia do sprite Vai ser muito útil, mas você também pode clicar com o botão esquerdo sobre ele e ver que está definido como valor zero. Agora queremos passar para 0,1. Se você ainda não escolheu aplicar encaixe ao cursor da linha do tempo, você pode fazer isso aqui Isso tornará muito mais fácil ir para 0,1. Acho que você também pode digitar manualmente o valor se quiser entrar na linha do tempo No entanto, costumo tirar fotos com o cursor do mouse. Em seguida, clique com o botão direito na seção do quadro, na linha do quadro e insira a tecla. Agora você obterá uma linha que vai entre eles. Essa linha significa que não há mudança de valor entre aqui e aqui. É apenas uma continuação do mesmo valor. Então, queremos clicar aqui e mudar isso para um, e isso significa que agora ele reproduzirá o segundo quadro da animação. Como a folha Bright é como uma matriz de valores, ela começa em zero, não em um. Geralmente, na programação, é assim que funciona. Então, um é na verdade o segundo quadro da animação e zero é, na verdade, o primeiro quadro da animação. Vamos clicar com o botão direito do mouse em 0,2, inserir uma chave, clicar no ponto do quadro-chave e, em seguida, alterar o valor para dois e, em seguida, ir aqui para 0,3. À direita, clique na tecla de inserção. Clique aqui, mude para três. Agora, você não deve mais ver nenhuma linha entre nenhum desses quadros. Podemos começar aqui, clicar em play e aí está nossa animação para o personagem. Agora, mais uma vez, como estamos fazendo apenas animação à esquerda e à direita, precisaremos fazer apenas uma animação de ídolo, uma morte e uma corrida aqui E então controlaremos a inversão do personagem de uma maneira diferente . Eu vou te mostrar isso mais tarde. Portanto, uma configuração muito mais simples e muito mais fácil de adicionar novos personagens, se você quiser fazer isso Então, vamos realmente duplicar essa animação porque muito disso vamos reutilizar Vamos apenas alterar talvez o valor do quadro He e a textura. E dependendo de quantos quadros de execução existem, podemos alterar os quadros aqui também. Mas vamos duplicar clicando aqui na animação e duplicar, e vamos fazer Ok, agora queremos clicar na textura, arrastar e soltar a planilha run sprite e ir até aqui Podemos ver que isso tem seis quadros de animação. Então, o que isso significa é que precisamos alterar o valor dos quadros H aqui para seis. Queremos alterar a duração da animação para 0,6 porque estamos trabalhando em seis quadros agora, não em quatro. E então vamos querer ir para 0,4 segundos e adicionar o quinto quadro da animação. Então insira a chave, clique aqui, altere o valor para quatro no quinto quadro e depois vá para 0,5 segundos. Clique com o botão direito aqui, insira a tecla, à esquerda, clique no quadro-chave, altere o valor 4-5 e pressione play E aqui está nossa animação redonda. Portanto, a duplicação economiza muito tempo. Ok, agora vamos adicionar a animação da morte enquanto estamos em andamento. Então, vamos duplicar e adicionar a morte. E então queremos mudar a textura aqui, é claro, para a folha da morte da noite. Então, arraste e solte a folha de morte no inspetor de quadros-chave Eu posso contar aqui. Há seis quadros. Então, vamos clicar. Na verdade, não precisamos mudar mais nada porque apenas o duplicamos de um lado para o outro. Podemos simplesmente clicar em Play. Mas você pode ver que está girando. Então, os personagens geralmente não fazem isso. Então, queremos realmente desativar o loop clicando duas vezes aqui. Isso fará com que a animação seja repetida para frente e para trás. Tipo, vai até o final e depois volta ao início. Isso seria mais útil para algo como uma plataforma móvel. Queremos clicar uma segunda vez para desativar completamente o loop. Então vá para 0.0, aperte play e a animação deve parar aqui no final. E depois que a animação da morte for feita posteriormente, só precisamos fazer algo como decifrar um fim de jogo para nosso personagem, e pronto. Ok, então qual animação realmente será reproduzida quando rodarmos o jogo? Bem, vamos clicar em play e descobrir. Ok, então você pode ver que a animação ociosa está lá, mas na verdade não está reproduzindo nenhuma animação Na verdade, não configuramos uma animação para reprodução automática no início Nossas animações acabarão sendo controladas com algo chamado máquina de estado Isso será o que abordaremos mais no próximo vídeo. Vamos clicar no reprodutor de animação e mudar a animação aqui que estamos vendo da morte à corrida. E clicaremos aqui neste pequeno botão de Reprodução Automática ao Carregar Então clique em reproduzir e agora você verá que, independentemente de nosso personagem estar se movendo ou não, ele reproduzirá a animação de corrida. Observe que ele também não muda de direção automaticamente. Esse será um script simples que também adicionaremos mais tarde. Mas temos três animações em nosso personagem e podemos alternar entre elas chamando-as pelo nome No próximo vídeo, criaremos a máquina de estado com um estado de movimento que poderá alternar entre ocioso e Executar 6. Máquina de estado do jogador: Ok, então nosso personagem tem um reprodutor de animação e a habilidade de reproduzir a animação de corrida, mas queremos alternar entre animações de ídolo e de corrida, dependendo se há uma entrada importante para nosso personagem ou Então, vamos controlar isso com uma máquina de estado. Então, se você se lembra, no início do curso, adicionamos o Limbo AI, que é uma máquina de estados e sistema de árvore de comportamento que você pode usar imediatamente no Gado, economizando muito trabalho, sem precisar fazer isso manualmente Vou usar máquinas estaduais para o curso. Acho que é um pouco mais fácil trabalhar com eles daqui para frente e muito melhores para configurações simples como essa E isso é, para ser honesto, uma configuração muito simples. Então, vamos clicar com o botão direito do mouse no jogador na base em um nó secundário. E vamos procurar a palavra-chave limbo. Então você verá aqui Limbo HSM estado hierárquica Como no nó raiz aqui, a própria máquina de estados controlará os estados, os estados do limbo, e será capaz de alternar entre eles à medida que adicionamos transições entre esses Então, vamos criar o Limbo HSM. E então eu vou clicar com o botão direito do mouse aqui e vamos adicionar nosso primeiro estado, adicionar um nó filho. Então, queremos um estado limbo e simplesmente criá-lo. Portanto, a hierarquia é a máquina de estados raiz, e todos os estados são o que podemos alternar entre E cada um desses estados executará código diferente, dependendo do estado em que o personagem está. Para este curso, na verdade, só teremos um estado de mudança e um estado de morte. Então, muito simples. Mas ainda é importante porque queremos saber quando nosso personagem deve passar para o estado de morte, e o estado de movimento controlará as animações de inatividade e movimento Tecnicamente, você pode separar Idle e mudar para seus próprios estados, mas eles basicamente executarão o mesmo código porque, independentemente de o personagem estar o mesmo código porque, independentemente de o ocioso ou em movimento, o movimento do personagem ainda é livre É só uma questão de qual animação ele vai reproduzir. E eu não acho que isso necessariamente justifique um estado completamente separado Então, vamos clicar com o botão direito do mouse no Limbo HSM, e eu vou anexar um script a Isso será chamado, digamos, de player underscore HSM. Portanto, é a máquina de estado hierárquica do jogador. Vamos criar isso. E então, aqui no topo, vamos, é claro, dar a ela o nome da classe, player HSM modo geral, como mostrarei no sistema de arquivos aqui, se pesquisarmos HSM, o que quer que você coloque como minúscula para o nome do arquivo, você também gostaria de ter o nome da classe aqui, mas isso, é claro, tem letras maiúsculas e você pula os espaços porque esse é um símbolo de tipo aqui em cima claro, tem letras maiúsculas e você pula os espaços porque esse é É uma boa ideia manter esse nome e o nome do script sincronizados Portanto, o HSM do jogador nos ajudará a controlar o corpo do personagem do jogador por meio dos estados que existem no Limbo HSM Então, queremos pegar o jogador e configurá-lo como o agente que a máquina de estado controla. Ok, então primeiro, para nosso player HSM, queremos uma referência ao player que nossa máquina de estado gerenciará Então, vamos exportar var player do tipo player. E se definimos o nome da classe para script corporal do jogador do nosso personagem como jogador, isso deve aparecer bem. E você pode ver no inspetor aqui à direita que ele apareceu Então, se quiser, você pode clicar em Atribuir e atribuí-lo ao jogador agora mesmo. Isso significa que nossa máquina hierárquica de estados do jogador agora tem uma referência ao Então, o que queremos fazer é garantir que, no Rady, esse script configure a máquina de estado inicializando-a com o player como agente Então, vamos criar uma função, sublinhar Rady, e o tipo de retorno será nulo Quase sempre é para funções prontas, porque essa é uma função de nó padrão destinada a configurar seu nó, como em um desses nós aqui à esquerda, algo que existe dentro de sua cena depois que todas as suas propriedades foram definidas. Portanto, a função ready executa o código que, quando o objeto estiver pronto, executará algumas etapas finais de configuração É muito comum usá-lo antes que o objeto realmente comece a rodar na cena, mas seguindo as etapas essenciais de configuração final. Enquanto prosseguimos com isso, também vou apresentar alguns novos conceitos. Então, primeiro, a declaração de afirmação. Então, vamos digitar assert. Então, isso significa que você passa em alguma condição e espera que ela seja avaliada como verdadeira. Então, neste caso, o que queremos verificar é se o jogador realmente foi colocado no inspetor Sempre que você define uma variável de exportação aqui, basicamente depende do designer ou de quem está configurando o projeto do jogo para realmente preencher esses campos, e é muito fácil definir um deles, especialmente se você tiver muitos scripts rodando com essas variáveis de exportação Eles são muito convenientes para configurar coisas no inspetor, mas estão sujeitos a erros do usuário Portanto, podemos apenas afirmar que o jogador não é nulo. Agora você vê que eu faço um ponto de exclamação e depois um sinal de igual. O ponto de exclamação significa que você inverte tudo o que está tentando testar Portanto, se o jogador for igual a nulo, o que na verdade seriam dois sinais iguais, você verificaria se o jogador é Mas se você fizer um ponto de exclamação e um sinal de igualdade , estará dizendo que o jogador não é e, sempre que fizer uma declaração, você também terá a opção de passar uma mensagem de falha opcional Então, o que você quer dizer para quem está executando o script quando essa condição não foi verdadeira Então, nesse caso, eu gostaria que algo como agente do jogador fosse configurado no HSM Então, máquina de estado hierárquica. Então, estou apenas colocando aqui no topo, mencionando muito claramente que essa é uma máquina de estado hierárquica Então, se você tiver alguma dúvida sobre por que o HSM está, bem, está lá em cima, então vamos mostrar isso em ação Se eu executar a cena, não haverá erro porque definimos nó do jogador como referência na variável de exportação de um jogador. Mas se eu desmarcar o player aqui e o executarmos, você receberá uma mensagem de erro imediata Vai dizer que a afirmação falhou. O agente do jogador deve estar configurado no HSM. Portanto, a afirmação é apenas uma verificação para garantir que o que você espera que seja verdade é realmente verdade Portanto, escrever declarações contra uma condição é a ideia geral de testar dentro da programação em geral. Para ir mais longe do que isso, você escreveria testes unitários ou testes de integração usando uma estrutura de teste como GD Unit ou o teste unitário GUT Godot Isso definitivamente vai além do escopo desta série de cursos, mas é algo que você deve pesquisar se tiver tempo mais tarde, pois escrever testes garante que seu código esteja realmente bem escrito e possa ser útil a longo prazo. Pegando insetos cedo. Então, vamos continuar com isso. Só vamos usar essas pequenas declarações afirmativas como essa. Você pode ver como isso funciona. Se a condição falhar , recebemos uma mensagem que nos informa que, oh, esquecemos de definir algo que deveríamos ter definido Então, na verdade, é muito útil. Então, vamos garantir que, no Limbo HSM, mais uma vez, atribuamos o player E então vamos fazer a configuração do próprio HSM. Então, eu vou realmente fazer disso uma função separada porque isso vai fazer algumas coisas diferentes. Então, vamos criar outra função aqui embaixo, função. E quando eu digo função, eu realmente quero dizer FU e C, basta dizer. sublinhado configurou o HSM e, em seguida, os parênteses, a seta giratória e o vazio Então, o que queremos chamar na máquina de estado é inicializar e precisamos passar um agente Como mencionei, o agente, neste caso, é o jogador que passa o jogador e, em seguida, precisamos chamar o HSM configurado Dentro da função pronta. Então, sublinhe a configuração do HSM. Ok, então, para explicar isso, estou tornando-a uma função privada com o sublinhado aqui, que significa que só devemos executar isso dentro desse script HSM do player A inicialização faz toda a configuração em segundo plano da máquina de estado e fará com que ela opere com o player como agente A outra coisa que precisamos fazer aqui é definir o estado inicial. Então, qual estado vamos executar primeiro? Vamos também renomear o nó Limbo HSM para player HSM. Também gosto de manter esse tipo de sincronizado com o script anexado a ele Então, toque HSM aqui. É igual ao player HSM dentro da janela da cena. E então o estado Limbo aqui, chamaremos isso de estado de movimento e anexaremos um novo script a ele Além disso, se você renomeá-lo antes de anexar o script, se você clicar com o botão direito do mouse no estado e anexar o script agora, verá que o nome do script também é padronizado para o nome do Portanto, manter essas três coisas sincronizadas geralmente é uma boa ideia para manter as coisas organizadas E vamos salvar isso na pasta do player por padrão por enquanto, e vamos herdar do estado Limbo Crie. Ok, então eu vou chamar isso de estado de movimento, nome da classe estado de movimento. Na verdade, podemos reutilizar isso para o inimigo também. Uma vez que todos eles usarão essencialmente a mesma configuração de animação. Então, no estado de movimento, precisaremos dos nomes de duas animações, que são nossa animação ociosa e nossa animação em movimento, que é Então, eu vou dizer export para Idl anim, e vamos configurar esse tipo para um nome de string E vamos padronizar o valor para Idle. Agora, colocar o e comercial aqui para torná-lo um nome de string é, na verdade Quando é declarada como um nome de string aqui, a variável, ela será convertida automaticamente. Portanto, é opcional se você quiser fazer isso como Ah, então vamos fazer export var. Vou chamá-la de run animation porque é assim que ela será chamada por padrão neste projeto, e faremos equals e ampersand Colocar alguns comentários aqui duas hashtags, faz com que os comentários apareçam no inspetor Então, se eu for até o inspetor e passar o mouse sobre a animação ociosa, você pode ver que os comentários realmente aparecem lá automaticamente, o que é Você também pode ver como a propriedade é definida como um nome de string com um valor padrão de idle ou run para o. Para isso, queremos ter certeza, verificando o player de animação, de que nossos nomes coincidem Então você pode ver que eu estava fazendo um ídolo em minúsculas, uma corrida em minúsculas. É sensível a maiúsculas e minúsculas quando você usa essas cordas. Portanto, certifique-se de que corresponda aqui e aqui, o que quer que apareça no reprodutor de animação para inatividade e execução Ok, então vou clicar com o botão direito do mouse no nome do estado do Limbo aqui e procurar o símbolo E você verá que há vários métodos especiais para entrar, sair, configurar e atualizar esse nó . Portanto, esses são métodos específicos do estado. Eles soam meio parecidos. Para o que você teria em um nó Gadot padrão. Mas a diferença é que eles só são executados quando a máquina de estado está realmente usando esse estado. A máquina de estado executa apenas o código de um dos estados por vez, e os outros estados basicamente ficam lá passivamente até a máquina de estado determine que é hora de fazer a transição para um estado diferente Isso significa que você pode escrever basicamente quatro conjuntos de código e apenas um será executado por vez, e isso é muito útil para evitar que coisas desnecessárias aconteçam enquanto seu personagem não deveria estar fazendo essas coisas Por exemplo, um personagem não deveria atacar quando está apenas correndo e não há nenhuma entrada de ataque Portanto, você não permite que esse código seja executado gerenciando-o com uma máquina de estado. Ok, então queremos começar com essa função enter. A palavra-chave virtual para essas funções aqui significa que, embora possa haver uma implementação padrão para a função, podemos escrever nosso próprio código personalizado, que muda completamente o que ele faz quando essas funções realmente são executadas. Vamos dar uma olhada no script de estado de movimento e vamos fazer a função underscore Enter Então, o que queremos que ocorra quando o estado de movimento entra dentro da máquina de estado? Então, queremos pegar o reprodutor de animação e definir sua animação para inativa ou executada dependendo se o personagem está se movendo ou não Ok, agora para o nosso estado de movimento, como vamos obter uma referência ao player de animação? Então, a ideia é que, para nosso agente, ele tenha apenas um reprodutor de animação, o reprodutor de animação do jogador. Existem várias maneiras de realmente obter essa referência dentro do seu script Move State. Vou tentar mostrar aquela que, do alto da minha cabeça, acho que seria a mais prática aqui. Então, se formos para o player HSM , podemos exportar uma referência para o player de animação Então, vamos exportar o player de animação var e, em seguida, o player de animação Colon Ok, um comentário para deixar claro que esse é o reprodutor de animação do jogador, e então o atribuímos no inspetor Agora, a razão pela qual estou fazendo isso neste script, em vez dos scripts infantis, como nos estados, é que eu quero apenas uma referência exportada aqui e, em seguida, usaremos isso para obter o reprodutor de animação dos nossos scripts de estado Então, se entrarmos no script de estado de movimento, eu poderia rapidamente obter a referência que o player HSM aqui no topo tem fazendo algo como get parent e depois dot animation player Então, isso é realmente tudo que você precisa fazer lá. E agora podemos atribuir isso a uma variável local, se quisermos. Outra opção seria ter um método que sempre obtivesse isso ou armazená-lo em cache aqui localmente. Então, só precisamos pegar esse valor aqui e atribuí-lo a uma variável local. Até agora, vou dizer reprodutor de animação de sublinhado, que é do tipo reprodutor de animação Então, pode estar em Enter, mas vou alterá-lo para configuração mais tarde. Vamos fazer o Underscore Animation player. Iguais, Get Parent. Sim. Você pode vê-lo como preenchimento automático, livrou-se do nome da função lá Esta deve ser sua linha completa aqui. No Enter agora, ele atribuirá o reprodutor de animação a qualquer que seja o reprodutor de animação dos pais. Então, isso torna tudo um pouco mais fácil do que ter que ter referência de variável de exportação em cada um desses scripts de estado. Em vez disso, os scripts de estado dependem apenas o pai ter uma referência ao reprodutor de animação, que eu acho justo, porque o HSM do jogador realmente controlará as animações do player de qualquer Então, acho que a configuração faz sentido nesse caso. Agora, em vez de usar Enter, que será chamado toda vez o personagem entrar no estado, implementarei a função de configuração. Função, configuração de sublinhado e, em seguida preenchimento automático que retorna vazio Vamos pegar essa linha e colocá-la aqui desse jeito. Portanto, a configuração só é executada uma vez quando a máquina de estado é inicializada Então, basicamente, não precisamos obter o reprodutor de animação toda vez que entramos no estado, apenas uma configuração definida. Agora, o que queremos que ocorra em Enter é que toquemos a animação certa. Então, no momento, não temos a maneira correta de determinar a animação porque nosso código para isso está, na verdade, preso no script do player, com essa direção sendo definida como uma variável local Então, teremos que retirar isso mais tarde para que funcione totalmente. Mas o que podemos fazer agora é reproduzir pontos no player de animação e digamos que vamos começar com a animação ociosa Agora, não, estou colocando a variável aqui, uma referência à animação ociosa, que resolverá o nome da string Então, isso espera um nome de string, mas não é difícil digitar isso aqui Queremos ter certeza de que é a variável para que ainda tenhamos a opção de alterá-la no inspetor, se isso fizer sentido Geralmente, via de regra, se você tem algo que deseja alterar, que é uma string, você deseja trazê-la para algum tipo de variável em vez de digitá-la toda vez que fizer referência a ela no mesmo script Às vezes, se a mensagem só for usada uma vez naquele local específico, não há problema em digitar a string do seu código no código da função. Isso também pode ser bom. Ok, então ele reproduzirá a animação inativa assim que o estado de movimento começar Agora, para testar isso, queremos desativar a execução automática dentro do player de animação. Ou talvez não o façamos, na verdade. Vamos parar o jogo e executá-lo como está, e ele deveria realmente entrar na animação inativa, ou assim eu pensei Então, vamos tentar desligar a reprodução automática ao carregar aqui. Agora, sem o Autoplay no carregamento, acho que não deveria funcionar nada Então, ainda temos o problema de parecer que o estado não está entrando porque a animação não está sendo reproduzida. Então, o que podemos fazer para provar isso é voltar ao editor de scripts. E vou definir um ponto de interrupção aqui clicando com o botão esquerdo à esquerda do número da linha no script. E isso significa que, quando atingir essa linha de código, ela será interrompida e nos permitirá ver o que está acontecendo no debuker Então eu vou apertar play, e não vai bater lá, que significa que o estado nunca realmente entrou. Não está ativo. Isso significa que precisamos voltar ao script do HSM e garantir que o estado de movimento esteja realmente ativo no início do jogo Então, vamos entrar no player HSM. E acho que o que eu esqueci aqui foi realmente chamar set ativo no próprio player HSM Então, queremos definir ativo como verdadeiro. Inicializamos, o que executa a configuração, mas não o ativamos, que na verdade faz com que a máquina de estado comece a funcionar Então, agora, se clicarmos em play, atingiremos a linha Enter no estado de movimento. Então, isso prova que o estado de movimento está realmente sendo reconhecido pela máquina de estado Para detalhar um pouco mais, você pode observar o rastreamento da pilha na parte inferior e ver, se ler com atenção, que a função de entrada do estado de movimentação foi executada e executada após a execução do HSM de configuração, e você pode realmente clicar aqui e pular para a linha de código, o que fez com que Enter fosse e você pode realmente clicar aqui e pular para a linha de código, o executado no estado de movimentação Consulte set Active true aqui, que chama Enter no primeiro estado executado. E tudo isso ocorreu, se você clicar na linha inferior do HSM pronto para configuração Então você pode ver, basicamente, o que fez com que entrasse fosse chamado. Então, foi a função pronta no HSM chamada de configuração HSM, que chamada set active e, em seguida, set active fez com que o estado de movimento Então, agora, se ainda não o fez, você pode desmarcar esse ponto de interrupção e clicar aqui para continuar ou pressionar F 12 no teclado e ver que o estado ocioso será executado Se você quiser mudar isso para o estado de execução, então vamos executar aqui e substituir play Idle pela animação play run, clique em play E agora você pode ver que ele está reproduzindo a animação de execução quando o estado entra. Então, no próximo vídeo, vamos nos concentrar em realmente controlar o estado do movimento com a entrada do jogador para garantir que estamos reproduzindo a animação certa no momento certo. 7. Entrada do jogador como componente: Nosso estado de movimento é reproduzir a animação no reprodutor de animação do nosso personagem, mas no momento ele não tem o código para saber quando mudar para a animação de execução, quando há uma entrada real do jogador. Então, para lidar com isso, se olharmos o script do jogador, podemos ver que é aqui que a direção está sendo adquirida para o jogador, e estamos fazendo isso com uma variável local para a direção. Então isso funciona para essa função de processo físico, mas não podemos usar a direção de entrada em nenhum outro lugar, exceto aqui. Então, gostaríamos de trazer isso para algum tipo de variável de propriedade que possa ser acessada por outros scripts. Agora, poderíamos fazer algo como direção VR aqui do vetor dois e depois mudar aqui para definir a direção da variável local. E essa provavelmente seria a opção mais simples. Juntos. No entanto, acho que se continuássemos seguindo esse caminho e colocassemos todas as informações dentro do script corporal do personagem do jogador , estaríamos realmente quebrando uma separação de preocupações. Portanto, o script corporal do personagem do jogador consiste principalmente em mover o jogador. Se adicionarmos todas as funcionalidades de entrada, adquirindo todas as informações dos jogadores , agora o script servirá a dois, três ou até mais propósitos à dois, três ou até mais propósitos medida que continuamos bagunçando o script do player Então, vou tentar trazer isso para um script de nó separado que nosso script de jogador ainda pode usar, mas também podemos fazer referência a, digamos, nossos estados para lidar com todas as entradas de nosso personagem de jogador. Então, vamos clicar com o botão direito do mouse no nó do jogador e eu vou adicionar um nó filho. Vamos digitar node aqui. Então, essa será apenas uma classe básica de nós, create. E eu quero renomear isso para ser a entrada do jogador. Vamos anexar um script a ele. Clique com o botão direito do mouse em anexar script, entrada do player. E podemos dar a ela o nome da classe entrada do player para que ela possa ser facilmente referenciada em uma variável de exportação Agora, a partir do nosso script de player, precisamos basicamente pegar isso, e eu vou controlar C, colá-lo na entrada do player, para que eu possa colocá-lo lá. Mas onde queremos realmente obter a direção é dentro do método de entrada. Então, agora no script do jogador, processo físico está executando cada quadro de processamento físico do nosso jogo, o que, por padrão, é algo em torno de 60 vezes por segundo Provavelmente não estamos pressionando as teclas 60 vezes por segundo, então essa é uma chamada vetorial muito desnecessária e provavelmente não importaria muito para o personagem de um jogador. Mas, em geral, acho que pode ser um pouco melhor no script do player lidar com a entrada de direção dentro do método de entrada de sublinhado da função Então, a função underscore input, basicamente, sempre que um evento de entrada for enviado para o jogo, ele passará por esse método e verá se há algum código para responder E a maneira de verificar se o evento é realmente relevante para nós é basicamente verificar o nome da ação no próprio evento. Então, vamos digitar if, e eu vou criar um novo método se o sublinhado for ação de movimento E vamos passar o evento para essa função. Então vamos fazer algumas coisas. Caso contrário, vamos simplesmente passar e não fazer nada ainda. O que é a função de ação do movimento I? Normalmente, estamos apenas nos protegendo contra outros tipos de ações e só queremos processar a entrada se a ação for uma ação de movimento Então, diremos que função é ação de movimento. Do tipo evento, evento de entrada. E então isso retornará um booleano. Portanto, um booleano é um verdadeiro valor falso. É uma ação de movimento? Verdadeiro ou falso? Então, isso vai ficar mais ou menos assim. Retorne o evento que é ação e, na verdade, vamos apenas copiar e colar esses nomes por enquanto. Ok, então podemos ver aqui que estou repetindo a mesma string aqui que está aqui em cima Então, geralmente, eu tentaria trazê-los para sua própria variável separada. Mas nós poderíamos Sim, por que não fazemos isso agora? E então eu vou te mostrar um passo podemos ir além disso, até mesmo. Então, vamos colocar uma variável aqui, Var left action ou, na verdade, digamos que var left é do tipo string name, e será igual a esse valor aqui. Então, vamos Controlar C, copiar isso, colar aqui e, em seguida, selecionarei isso novamente. Vou pressionar Control R para localizar e substituir, e vou substituí-lo pela esquerda. Agora, quando você estiver usando essa ferramenta, ela substituirá o que você selecionou atualmente. Então, eu quero substituir isso nome à esquerda, então vou clicar em Substituir. Agora, a segunda, para a qual ele vai pular automaticamente ou talvez não. Uh, aqui, queremos manter a cotação Ampersand à cotação Ampersand Então, vamos clicar em Próxima partida, e descobriremos aqui embaixo que queremos substituí-la pela esquerda, então clique em Substituir. E isso vai ser basicamente isso aí. Provavelmente também deveríamos cuidar dessa mensagem de erro agora. Então, vou declarar essa direção distante e nos preocuparemos atribuí-la corretamente em um minuto Ok, para eliminar a mensagem de erro, você pode salvar o script por enquanto. Então, agora, a ação do movimento I está retornando se a ação é a ação da esquerda. Então, o nome da ação no evento corresponde ao nome restante? Agora, temos três outras ações, então precisamos verificar três outras condições aqui. Então, vamos revelar isso rapidamente. Vou selecionar esse Controle X para cortá-lo, digite corretamente. Vá até aqui, crie uma nova variável var right, nome da string igual e, em seguida, controle V para colá-la Portanto, temos a variável atribuída ao nome da string à direita. E faça a mesma coisa para cima. Então selecione isso. Controle X para cortar, digite. Desça até aqui. Var up é do tipo string name e é igual a Control V para colá-lo N. E apenas mais uma vez . Controle X. Digite abaixo, vá até aqui, abaixo, nome da string é igual, Controle V, cole Ok, agora temos nossas quatro variáveis que correspondem aos nomes reais das strings que estamos realmente passando para métodos como esse. Se quiser outro truque divertido, você pode tabulá-los assim, selecionar logo atrás da aba de acerto de sinal igual, atrás da aba de acerto senoidal igual, atrás da aba de acerto de sinal igual, atrás da aba de acerto de igual sinal, desse jeito E você pode realmente alinhar tudo isso e ficar bonito e tudo mais. Pode ser um pouco mais legível. Depende de você se você gosta de ter a aba ou não. Ok, mas agora o importante é terminar esse método, precisamos verificar as outras ações. Então, vamos fazer espaço. E então o caractere de linha reta, que é shift e logo abaixo do backspace, a linha vertical Então, a linha vertical, a linha vertical, e você tem que manter a tecla Shift pressionada para fazer isso, pelo menos no meu teclado. Então, essas duas linhas verticais significam ou. Eu acho que você poderia realmente digitar ou gostar disso, e seria o mesmo. E poderíamos tentar que, se isso realmente for um pouco mais fácil de ler e fazer, o evento ponto é ação, e queremos Right. Espere aí. Escreva o nome da variável. Bom. Então, parece que isso funciona. Então, vamos fazer isso de novo ou se eu aumentar a ação ou evento for ação negativa. Ok, então espero que isso faça sentido. Estamos verificando se o evento é ação esquerda, ação direita, ação positiva ou ação negativa. Agora, essa fila está meio longa. Você pode ver isso como um ponto de corte na vertical. Então, essas são apenas diretrizes gerais aqui. Você pode ver que temos 107 caracteres nesta linha. Não é um problema. Quer dizer, acho que é bem legível, mas se você quiser que seu código fique mais vertical , você pode dividi-lo aqui pressionando Enter Agora, se eu pressionar o Controle S aqui, isso vai nos causar um problema. Será a expressão esperada após ou. Portanto, atualmente não sabe que estamos tentando pular para as próximas linhas. Então, o que você realmente precisa fazer é colocar uma barra invertida logo após o O, e agora ele sabe que isso continua na próxima linha Então você pode continuar fazendo isso desta forma, inverta Enter para colocar uma nova linha e, em seguida, inverter Enter e colocar Agora, eu diria que isso parece bem limpo aqui. Então, temos nossas quatro condições, e ele verificará todas elas, e assim que uma delas for avaliada como verdadeira, ela retornará verdadeira E se nenhum deles for verdadeiro, então é falso. Então, se a ação for uma ação de movimento, poderemos processar nosso código de movimento. Ok, então é aqui que realmente atribuímos o vetor. Há dois lugares em que vamos usar a entrada. Uma é para a direção voltada e a outra é para a direção do movimento. Então, vamos pegar a variável para a entrada. A entrada Var é do tipo vetor dois, vamos defini-la igual ao vetor Importar ponto G. E, assim como antes, queremos esquerda, direita, para cima e para baixo. OK. E aí está nossa opinião. Então, sempre que pressionamos qualquer tecla, queremos definir a entrada direcional Então, a direção será igual a qualquer valor de importação. Mas com a direção voltada, é um pouco especial. Um personagem em um jogo de quatro direções e dois D não pode encarar o vetor 00 porque isso seria basicamente olhar para si mesmo, não olhar para a direita, para cima, para a esquerda ou para baixo, que são as únicas direções que ele pode olhar Quando atribuímos o vetor oposto, só queremos fazer isso se a direção não for zero Portanto, se a entrada não for igual ao vetor 20, para um vetor com duas direções de zero, isso significa que X é zero e Y é zero, lembre-se de que os vetores têm componentes X e Y. Então, dado que essa condição está definida, podemos pegar a face e configurá-la para a entrada. E vamos nos livrar desse pequeno passe aqui porque não precisamos disso. E então, no topo aqui, var voltado para o vetor tipo dois. Podemos simplesmente usar como padrão , digamos, o vetor de dois pontos à direita, o que funciona perfeitamente. Se sempre se espera que nosso personagem fique voltado para a direita por padrão durante o carregamento, é claro que você pode virar para a esquerda, se quiser. E então, na direção aqui, queremos substituir isso pelo vetor dois ou, se você quiser ser um pouco mais sofisticado, embora esse também seja o valor padrão, poderíamos dizer que dois pontos são iguais ao vetor Então, isso aqui na verdade significa que estamos inferindo o tipo da variável a partir da atribuição, e a atribuição é um vetor dois, que significa que isso será automaticamente atribuído a um vetor dois, que significa que você não precisa digitar esse vetor dois é igual ao vetor dois Isso parece meio engraçado. Então, da mesma forma, você também pode fazer isso aqui embaixo. E torne-o um pouco menos prolixo, embora ambos funcionem perfeitamente bem aqui A única desvantagem é que, se você transformar esse vetor de dois pontos à direita em algo como uma string, isso também estará tecnicamente correto, porque agora está atribuído à sequência do vetor de dois pontos à direita, e isso significa que agora é uma string e isso significa que agora é uma Então, você tem que ter um pouco de cuidado com isso. Na verdade, não vi isso ser um problema. Então, acho que nesses casos, inferir o tipo da variável em vez de declarar o tipo de variável diretamente é perfeitamente razoável e correto e, muitas vezes, um pouco mais Então, depende de você, você pode fazer as duas coisas. Se eu estou vendo as coisas corretamente, acho que esse é basicamente o nosso script de jogador por enquanto. Voltaremos e adicionaremos sinais um pouco mais tarde. Ok, então em nosso script de jogador, vamos mudar as coisas aqui. Então, em vez de ter uma variável local para direção e atribuir a direção em vez do processo físico, o que vamos fazer é clicar em Exportar var. A entrada é do tipo player E aqui no processo de física, o que queremos fazer é obter a direção da corrente a partir da entrada. Então, a direção var, e eu vou inferir o tipo da direção do ponto de entrada, será atribuída à direção local, e então usaremos isso para o resto do nosso script, verificando a direção é realmente um valor que não vetor 20 é o que essa linha significa E nesse caso, pegamos a direção e a multiplicamos pela velocidade A diferença agora é que a entrada é gerenciada por um script completamente separado. Nosso script de jogador é mantido mais limpo e temos um componente de entrada de jogador reutilizável que pode ser usado para designs de personagens completamente diferentes que precisam do mesmo tipo de entrada do jogador, mesmo que o personagem realmente lide com a mecânica de seu movimento de seu movimento Então, vamos clicar no script do player e queremos ter certeza de que a importação está atribuída. Então, como antes, o que poderíamos fazer é colocar a função, sublinhado pronto, afirmar que a entrada não é nula e dar entrada deve ser atribuída para o corpo do personagem se mova corretamente, execute o jogo e veja se nossa afirmação falha, o que é bom Clique no player e atribua a entrada à entrada do player, execute-a mais uma vez e veja se ela realmente funciona. E se você usar o WASD, poderá ver que ele está se movendo com base na entrada do nosso script de importação do player 8. Troque animações com sinais: No momento, nossa entrada direcional de cima para baixo, para a esquerda e para a direita, é controlada pelo script de entrada do player, mas ainda não temos as animações controladas pela direção desse script Então, se dermos uma olhada no script de estado do movimento, poderíamos imaginar que poderíamos simplesmente pegar uma referência à entrada do jogador e começar a usá-la como antes. Esse método, embora geralmente funcione bem, depende do script HSM do player, tendo uma referência a todas essas propriedades Se alterarmos o script da máquina de estado hierárquica do player , a qualquer momento, isso pode quebrar a forma como esse script funciona, e o script também tem uma espécie de dependência direta de o pai ter todas Portanto, não poderíamos reutilizar isso em uma máquina de estado completamente diferente que não tenha, digamos, um player de animação exposto Então, o que você pode fazer como outra opção é usar quadros negros Então, olhamos aqui à direita. Quando você seleciona o HSM, você pode ver que o plano Blackboard é uma Então, quando você cria um plano Blackboard, ele informa a qualquer nós-filho no sistema da máquina de estado a que ele terá acesso E, nesse caso, queremos a direção oposta da entrada do player. Então, vou criar um novo plano Blackboard aqui no HSM do player e clicar Podemos ir até aqui e adicionar uma variável, e queremos adicionar, vamos usar a face. Então, quando falamos sobre as animações, o que é mais relevante para nós é a direção que o personagem está tentando encarar , em vez da direção em que o personagem está se movendo Normalmente, seriam a mesma coisa, mas nem sempre. Então, teremos de frente para aqui e, na lista suspensa, o vetor dois, para que possamos clicar em Gerenciar aqui e adicionar uma variável E vamos procurar o vetor de direção dois. Portanto, mude o tipo de flutuador para vetor dois. E então podemos clicar em OK, então, para obter essa direção também e usá-la em nossos diferentes estados de máquina de estado, queremos ir para vinculação e, em seguida, direção, queremos vincular isso ao script de importação do player Mas se fizermos isso agora, nada vai aparecer. Portanto, uma das limitações do sistema Lambo AI é que, para vincular uma propriedade ao plano Blackboard, essa propriedade precisa ser Então, se formos para a entrada do player, podemos seguir a orientação aqui e simplesmente fornecê-la na exportação e depois salvar. Então você clica em Importar jogador, você verá que a direção aparece aqui. Tecnicamente, isso significa que você pode mudar a direção antes do início do jogo Ela será imediatamente substituída por essa função de importação assim que você pressionar uma tecla Portanto, não há realmente muita desvantagem. Só que a direção precisa ser exposta para que isso funcione. Então, no HSM, agora podemos nos vincular ao script de entrada do player e procuraremos a propriedade Então escolha a direção e clique em abrir. Ok. Então, se você leu isso agora, a direção agora está vinculada à direção de importação do jogador, o que significa que tudo o que definirmos na direção de importação do jogador será espelhado neste Blackboard, e poderemos usar isso nossos scripts, como o estado de Então, enquanto estamos nisso, também podemos configurar o player de animação no plano Blackboard, o que eliminará a dependência entre o estado e o HSM Vamos gerenciar e adicionar uma variável, vou dizer um player de animação. E vamos digitar e escolher o caminho do Node, acredito que é o que queremos aqui. Ok. Clique em OK. E atribuímos isso ao reprodutor de animação. Portanto, agora, se lermos no Blackboard o reprodutor de sublinhado de animação da propriedade, poderemos obter uma referência ao reprodutor de animação Ok, agora, se formos para Move State, a aparência disso será mais parecida com esta. Então, o player de animação underscore será igual ao Blackboard Portanto, o Blackboard é criado em tempo de execução, com base no plano Blackboard Então, esse é basicamente o objeto de tempo de execução em que obtemos as variáveis de que precisamos. Então, precisamos fazer Blackboard dot, Get VR, get underscore var e estamos procurando o nome da propriedade Então, neste caso, esse será o reprodutor de sublinhados de animação O padrão será nulo. Queremos que ele reclame se não conseguir encontrá-lo, porque isso significa que erramos em algum lugar em nossa configuração Agora, podemos basicamente remover essa linha agora, e agora nosso script não depende nem um pouco do script HSM Depende apenas da configuração do Blackboard para ter um reprodutor de animação, que receberá uma mensagem de erro se não tiver um reprodutor de animação no Blackboard Então, agora, para a direção, só precisamos atualizá-la , eu suponho. Então, funcione, sublinhe, atualize e obteremos a variável atual do Blackboard Então, essa será a direção da realidade virtual. Será igual ao Blackboard dot Get VR, e estamos procurando uma direção E não podemos inferir esse tipo de variável porque não sabemos o que o Git VR realmente retornará aqui Então, vamos declará-lo como um vetor dois. Ok, agora temos a propriedade de direção, e nosso script nem precisa saber nada sobre o script de entrada do player. Tudo o que precisamos saber é que o Blackboard tem uma propriedade de direção e podemos usá-la para nossas animações Então, de forma muito simples, se a direção não for zero, essa é a forma abreviada, então vamos reproduzir a animação de execução no reprodutor de animação. Então, sublinhe o player de animação, dot play, o run animation, Ale, o reprodutor de animação, o dot play, a animação inativa Então, vamos clicar em Jogar agora e ver se isso funciona. Então, se I WAS e D, você pode ver que obtemos o movimento de animação do nosso personagem. Agora, há uma grande falha aqui, que é que a compensação em nossos sprites não Agora, essa é apenas a natureza de como as planilhas de sprites específicas foram configuradas Acho que o tamanho de cada moldura não coincide. Então, isso cria um deslocamento. Agora, isso seria algo que você pode corrigir em um editor como O Sprite, se você for o artista, ou se quiser apenas fazê-lo funcionar Nesse caso, podemos fazer isso no reprodutor de animação Então, no reprodutor de animação, podemos ir para, digamos, vamos verificar a animação ociosa E aqui está centralizado aqui, como seria de esperar. Então, quando vamos para a animação de execução de Run, precisamos apenas ter certeza de que ela corresponde à animação ociosa Então, vamos querer enquadrar a posição em cada uma de nossas animações. Então, vamos adicionar uma faixa, faixa de propriedade. Vamos ver, o Sprite two D porque estamos falando sobre o deslocamento do sprite, não do deslocamento do personagem do jogador E então queremos uma posição aqui. Então, vamos adicionar uma chave. No momento, está em menos 14. Eu vou para Idle. E então vamos adicionar a mesma propriedade com antecedência. Então posicione dois D e, em seguida, adicione o quadro-chave aqui. O motivo pelo qual estou fazendo isso é porque a posição de marcha lenta já está correta, então não quero que essa alteração seja alterada ao configurar a corrida Enquanto estamos nisso, vamos verificar a Morte. Acho que a animação da morte está realmente no lugar certo. Então, tudo o que precisamos fazer é ir aqui, adicionar a faixa, sprite two D, posição Ok, insira a chave. Ok, e então isso deve ser bom. Então, agora precisamos alterar o valor da rodada para animação especificamente. Então aperte Q para ir para o Modo de Seleção. Clique com o botão esquerdo no sprite. Você deveria ter essa caixa grande. Você provavelmente pode ver de onde veio o deslocamento daqui, porque há muito espaço vazio aqui em cima Mas de qualquer forma, só precisamos pressionar W e depois mover isso para a direita. Deixe-me verificar a transformação. Sim, 27 pixels negativos. Acho que era isso que eu tinha e estava no rascunho do projeto. Então, vamos estruturar isso. Vamos clicar em Play e ver se isso é melhor. Então, o WASD está quase lá, mas acho que precisa estar alguns pixels mais alto Então, vamos W e , em seguida, movamos isso para cima. Vamos tentar 30, acertar W. N , ainda não está lá. Ok, vamos aumentar ainda mais. Vou ver a animação inativa. Ok. E é aí que seus pés estão no chão. Então, vamos voltar a correr. Ok, e seus pés devem estar aqui em cima, dois pixels abaixo da parte inferior. Ok, depois fique ocioso e depois corra. Ok, eu esqueci de enquadrá-lo. Então, deixe-me mudar isso mais uma vez. Não acho que precisemos do deslocamento X. Vamos enquadrar isso em menos 30 pixels aqui. Ok, vamos clicar em play e testar mais uma vez. WASD. Isso parece correto para mim. Então, vamos continuar com isso. Vamos pressionar Sop no player aqui. E só para ficar claro, para uma solução de longo prazo, provavelmente seria melhor corrigir as folhas de pico de animação e apenas garantir que todas tenham o mesmo tamanho, independentemente da quantidade de movimento nas animações, para que você não precise mexer longo prazo, isso é um pouco mais difícil de gerenciar, então é melhor fixá-lo diretamente na folha de animação. Ok, então, para nossos personagens ficarem ociosos e se moverem, a última coisa que realmente precisamos fazer movimento básico de nossos personagens é fazer com que eles girem quando estamos nos movendo para a esquerda e depois voltem para trás quando estamos nos movendo para a Esse será o próximo vídeo, então nos vemos no próximo. 9. Virando um personagem 2D: Então, temos nosso movimento de cima para baixo, para a esquerda e para a direita do personagem, e ele pode voltar ao estado ocioso. Isso é ótimo. O que precisamos mudar aqui, porém, é que nosso personagem precisa ser capaz de virar da direita para a esquerda, dependendo se temos uma entrada esquerda ou direita Então, queremos basicamente virar o nó do sprite da esquerda para a direita Agora, Sprite tem diretamente um flip H aqui. Certamente poderíamos simplesmente dizer em um script personalizado que inverta o H com base em tudo o que a entrada do player faz Para dar um passo um pouco distante disso. Em vez disso, o que poderíamos fazer é colocar um nó pai que se vira quando a direção voltada para a entrada do jogador muda, e então isso inverterá automaticamente o nó do sprite porque o nó do sprite é filho desse nó pai dois D. Então, se eu clicar no nó do jogador e adicionar um filho, vamos adicionar um nó dois D, e então eu vou chamá-lo de virar que se vira quando a direção voltada para a entrada do jogador muda, e então isso inverterá automaticamente o nó do sprite porque o nó do sprite é filho desse nó pai dois D. Então, se eu clicar no nó do jogador e adicionar um filho, vamos adicionar um nó dois D, e então eu vou chamá-lo de virar dois de frente para dois D. é clicar com o botão direito do mouse e anexar um script. Vamos colocar isso no local padrão, criar e fazer com que o nome da classe vire dois de frente para dois D. E isso vai virar a escala X na transformação, dependendo se o personagem está voltado para a esquerda ou Ok, então o que isso significa basicamente? Se eu pegar esses dois D brilhantes e colocá-los de frente para dois D, e então vamos colocá-los de volta onde estavam antes, no topo da hierarquia, vou virar para dois D e, aqui à direita, desmarcar a ligação entre X e Y porque estamos apenas alterando Está bem? Em seguida, digite menos um para o X e você verá que o caractere vira para a esquerda Se digitarmos um no X, o personagem fica voltado a direção original, que está à direita. Obviamente, você precisa ter um pouco de cuidado com a configuração. Se você colocar suas armas sob o controle de dois Dno, isso significa que suas armas também estarão voltadas para a esquerda ou para a Agora, às vezes você quer isso e, em outros casos, você não quer que seu sistema de lançamento de projéteis mais tarde, você não quer que ele gire com base na escala desse nó Mas se você colocasse, digamos, uma lança na mão do personagem, provavelmente gostaria que o sprite ficasse voltado para a direção certa quando você estivesse voltado para a direita ou para a esquerda quando estivesse voltado para direita ou para a esquerda quando Portanto, você só precisa ter cuidado com os nós colocados aqui, porque qualquer coisa que esteja invertida para dois D na hierarquia agora será invertida sempre que o nó pai for invertido Portanto, lembre-se do que está relacionado ao quê, e você ficará bem Então, dentro de nossa virada para dois scripts em D, queremos adicionar uma var de exportação E vamos dizer entrada, que é do tipo entrada do player. Agora, por enquanto, depender da entrada do jogador significa que esse script é especificamente do jogador e não necessariamente usado pelos scripts do inimigo. Para um script tão pequeno, nesse caso, pode valer a pena ter a referência direta à entrada do player, pois isso fornece a configuração mais simples e prática. E então, a única coisa que você precisa ter certeza é que a entrada está realmente atribuída ao inspetor Então, podemos fazer isso com o assert. Vamos sublinhar uma função já e , em seguida, afirmar que a entrada não é nula e dizer que, para inverter a referência à entrada do player, é necessário, mais uma vez, você sempre pode simplesmente ir até a reprodução mais alta e ela atingirá sua afirmação, para que o teste Caso contrário, neste ponto, podemos simplesmente obter o acesso ao sinal da entrada do player e usá-lo para inverter esse nó sempre que a direção da face mudar Se bem me lembro, ainda não coloquei os sinais. Então, se clicarmos com o botão direito do mouse na entrada do player, procurarmos o símbolo, queremos ir até o topo e declarar alguns sinais Então, um sinal é como um evento. Se você vem de outras linguagens como C Sharp, é um evento. E, nesse caso, isso significa que algo é acionado dentro do seu código e você deseja notificar os objetos assinantes que algo ocorreu e opcionalmente, passar algumas informações ou dados contextuais para o Ok, então deixe-me declarar uma, e depois explicarei de forma um pouco mais simples Então sinal é a palavra-chave, e então diríamos que face mudou, e gostaríamos de passar na direção em que ela mudou também, para que pudéssemos dizer valor ou face, e esse será um fator de tipo dois. Então, estamos declarando o parâmetro. O que estamos enviando para qualquer objeto receptor está entre parênteses Então, a face do sinal está mudada. Portanto, no evento, sempre que a propriedade de face, neste caso, aqui embaixo muda, queremos enviar um sinal que permita que qualquer objeto inscrito saiba que o valor de face mudou Então, nesse momento, eles podem responder a isso em seu próprio código. E isso significa que você não precisa verificar constantemente a propriedade de face da entrada do player em cada atualização de quadro. Basta esperar que o script o notifique de que o valor realmente mudou para algo diferente. Portanto, você tem essas informações significativas e só precisa atualizá-las uma vez a cada poucos segundos, porque o jogador só mudou a direção do movimento uma vez cada 3 segundos ou a direção voltada para o lado oposto neste caso. Em outras palavras, você se torna dependente de um sinal acionando seu outro código, em vez verificar constantemente um valor para alterações manualmente Então, com nossa propriedade voltada aqui embaixo, queremos pegá-la e adicionar um setter para que, quando o valor de face mudar, nós realmente emitimos o sinal sempre que ele Então, se você adicionar dois pontos no final, isso permitirá que você declare seus setters e getters Você pode simplesmente fazer um deles. Você não precisa fazer as duas coisas. Então, neste caso, queremos dizer valor definido. E observe que isso está em uma nova linha. Então, neste caso, estamos realmente declarando uma função, na verdade E isso só é executado sempre que definimos o valor dessa propriedade para algo novo. Então, estamos alterando o padrão de apenas definir o valor e não fazer mais nada para configurá-lo e fazer algum código extra. Então, quando definimos o valor, queremos pegar a face e defini-la como o valor. Então, isso seria o que ele faz por padrão. Se você não declarar nenhuma função setter Getter, o Getter seria mais parecido com isso, voltado para o retorno, certo? Isso é o que você esperaria. Você acessa a propriedade pelo nome, frente para frente, e ela retornaria o valor com o qual está definida. Portanto, se você não precisa de código personalizado para o Getter, não precisa declarar isso porque é isso que ele faz por padrão, e é isso que o facing faria por Agora, se você quiser fazer algo como emitir um sinal, precisará do código extra Então, agora queremos dizer que a face mudou o nome do ponto emitido do sinal, então emitimos o sinal, que significa que qualquer objeto se inscreva nele agora será notificado, mas queremos passar as informações da Então, passamos de frente. Então, estamos pegando esse valor, enviando-o por meio do sinal e, em nossos outros scripts, receberemos essa informação e podemos decidir o que fazer com ela. Agora, há um outro truque que eu quero mostrar aqui, porém, que é que não queremos que a mudança de face seja emitida sempre que definimos o valor de face Isso pode estar sendo definido com o mesmo valor em cada quadro. Acho que a verificação da ação de movimento na verdade evita isso, porque isso só seria acionado quando houvesse uma ação de movimento real, que seria, nesse caso, como pressionar a tecla certa ou soltar a tecla certa ou o mesmo nas outras direções. Mas é sempre bom ser mais defensivo na programação Basta supor que suas outras suposições não estejam necessariamente corretas e, em seguida, se proteger contra elas Então, vamos colocar um guarda aqui. Se a face já for igual ao valor, isso significaria que não há mudança. Então, nós só queremos voltar aqui. Não precisamos definir face porque o valor já está atribuído à face. Já está correto e não precisamos emitir o sinal e não devemos emitir o sinal porque o valor na verdade não muda Portanto, temos essa proteção contra conjuntos defeituosos na propriedade oposta. Mas se esse guarda for ultrapassado, colocamos a face e emitimos o sinal Então, com tudo isso, o sinal agora será emitido. E podemos simplesmente virar para dois D. E depois de afirmarmos que Importar não é nulo , sabemos que Então, podemos ir para a entrada voltada para o ponto alterado. Você verá que o sinal é realmente referenciado pelo nome aqui e tem aquele pequeno símbolo ou sinal de Wi-Fi Então, alteramos as faces dos pontos de entrada. Agora estamos vendo o nome do sinal e queremos nos conectar a ele. Então, não se conecte. E o que queremos conectar a ele? Bem, isso seria uma função chamável que configuramos aqui Para manter as coisas, acho que, o mais simples possível, devemos criar uma função personalizada na parte inferior. Então, eu vou dizer que o underscore facing mudou. Ainda haverá um erro porque não há nenhuma função com esse nome dentro do nosso script. Então, se eu pressionar Enter algumas vezes, diremos função, sublinhado na face alterada Agora, quais parâmetros essa função vai usar? Bem, vai levar o que foi passado para o sinal. Então, neste caso, você estaria olhando para a direção oposta. Então eu vou dizer P, com o sublinhado virado, P como parâmetro, deixando bem claro que esse valor vem dos parâmetros que foram passados para a função E então esse é um vetor dois. Não vamos devolver nada, então estamos retornando vazios E agora podemos escrever o código para responder à alteração da face emissora do sinal Ok, então quando a face é alterada, queremos pegar a direção X da face e usá-la para determinar se devemos ficar voltados para a direita ou para a esquerda. Então, se p ponto voltado para o ponto X é um valor positivo, então o que queremos fazer é pegar a escala X desse nó dois D, virar para o nó voltado para o nó oposto, e queremos defini-la igual ao valor absoluto do ponto da escala X. Quando você pega o valor absoluto, você está fazendo um número sempre positivo Então, para encarar a direita, estamos fazendo maneira certa nossa direção positiva. Portanto, sempre queremos ficar voltados para a direita sempre que a entrada estiver realmente voltada para a direita. Agora, não vamos dizer mais nada. Vamos dizer outra coisa se P voltado para X é menor que zero, então não queremos esse caso zero porque nossos personagens não deveriam ser capazes de encarar o ponto 00 no vetor dois que realmente não existe como direção inversa para esse tipo de jogo de dois D. Portanto, não queremos fazer nada quando for esse o caso. É por isso que estou verificando se o valor é menor que zero, porque menos de zero estaria realmente voltado para a esquerda. Então, fazemos o ponto X escalado, e vamos definir isso igual a menos uma vezes o valor absoluto do ponto X. Ok, então isso sempre dará um número positivo e, em seguida, sempre o tornaremos negativo vezes o valor absoluto do ponto X. Ok, então isso sempre dará um número positivo e, em seguida, sempre o tornaremos Portanto, provavelmente existem algumas maneiras diferentes de calcular isso aqui, mas acho que deve funcionar bem. Ok, então vamos para duas vistas em D. Clicamos em flip para virar dois D e atribuímos a entrada do player Ok, então é aí que vamos obter o sinal. Vamos nos conectar a ele em Rudy em nosso roteiro frontal Ok, então se eu apertar play, vamos fazer o movimento certo. Nosso personagem fica voltado para a direita e, se eu apertar para a esquerda, nosso personagem fica voltado para a esquerda. Se virarmos no canto superior esquerdo, estamos voltados para a esquerda. Se virarmos para a direita, estaremos virados para a direita. Basta testar todas as oito direções em que nosso personagem pode se mover com a entrada do teclado, e isso parece bom para mim. Então, só para pensar um pouco no futuro, uma coisa que podemos fazer é pegar esse código e transferi-lo para uma função diferente, refatorando-o em uma Então, digamos que a função atualize , gire, e isso exigirá a direção oposta Então, voltado para P, vetor dois, e então eu vou pegar isso, cortá-lo aqui e, na face alterada, vou chamar update flip P facing Agora, o motivo para fazer isso é para que eu também possa reutilizá-lo quando estiver pronto Então, quando estiver pronto, diremos apenas atualizar e virar a importação voltada para o ponto Então, quando nosso script é carregado pela primeira vez, queremos definir a direção voltada para cima imediatamente antes qualquer importação realmente venha do nosso player, porque pode ser o caso em que decidimos, digamos, na entrada do player, exportar essa direção voltada e, em seguida, alteramos o padrão de ponto vetorial à direita para vetorizar dois pontos à esquerda, porque, por qualquer motivo, queremos nosso a serem virados para a esquerda por padrão. Agora, com isso, podemos estar preparados para isso inicializando automaticamente com a direção de giro correta com base no que quer que a entrada esteja dizendo Então, agora, essa é uma função pública. Poderíamos simplesmente chamar isso de outro script se houvesse um caso não relacionado à importação em que quiséssemos mudar a direção de inversão do personagem Por exemplo, talvez durante uma cena, você queira cortar todas as entradas do player e chamar isso manualmente. Então, seu personagem estava voltado para a direita e, na cena, você quer que ele fique voltado para a esquerda. Portanto, você teria a opção de simplesmente chamar Update flip on the flip to facing two D node. Ok, então definitivamente abre algumas possibilidades. E isso é praticamente tudo o que precisaremos fazer para o movimento WASD do nosso jogador Está parecendo bom. Acho que todas as preocupações estão bem separadas 10. Camadas de mapas com grama e terra: Ok, então, como o movimento e a animação de nossos personagens basicamente jogam tanto no Idol quanto no Run, incluindo a direção invertida, acho que agora é um bom momento para começar a colocar um plano de fundo para que o jogo fique um pouco mais bonito, em vez de apenas ter o fundo cinza padrão do Gadot Então, vamos seguir em frente e mudar para o nosso cenário mundial. Se você não tiver isso aberto, você pode ir para o canto inferior esquerdo aqui. Basta pesquisar o mundo e você poderá encontrar o mundo dottScn se esse for o mesmo nome que você estava usando como eu E então, na hierarquia mundial, queremos clicar com o botão direito do mouse e adicionar um novo nó, e estamos procurando por uma camada de mapa de mosaico Você pode ver que havia outro nó chamado Tilemap, mas ele está obsoleto, eu acredito, desde 4.3, e desde 14.41 e prestes a ir para 4.5, é definitivamente recomendado que você mude para camadas de tilemap, que divide o tilemap em nós de camada individuais em vez de ter cada camada. camada. Contido dentro de um mapa de blocos. Então, vamos adicionar uma camada de mapa de mosaico. E vamos chamar isso de algo como ground, então vou renomeá-lo para ground E se você a tiver selecionado na parte inferior, deverá ter a janela do mapa de blocos Então, abra isso se ainda não estiver aberto. E então precisamos encontrar os ativos artísticos do nosso projeto. Então, vou abordar arte e, em seguida, conjuntos de ladrilhos de ambientes Pixel Crawler, e vamos querer trabalhar com os pisos Então, para que possamos fazer isso, não queremos estar no mapa de blocos, mas sim na guia do conjunto de blocos Olhe no canto superior direito enquanto você tem a camada do mapa de mosaico selecionada e você verá o conjunto de mosaicos como um recurso que você pode atribuir aqui. Você deseja clicar com o botão esquerdo e fazer um novo conjunto de blocos Depois de fazer isso na parte inferior, haverá uma nova guia Tilset Então, depois de renomeá-lo para chão, olhe para o canto superior direito com ele selecionado e você verá um campo para o conjunto de blocos Então, queremos clicar aqui e declarar um novo TilesetrSource Você faz isso na parte inferior, deve haver duas guias aqui relacionadas ao mapa de blocos, que é um mapa de blocos para realmente selecionar e desenhar esse conjunto de blocos, que serve para configurar seus blocos e, em seguida, um mapa de blocos para desenhar seus blocos Então, queremos ir para o Tile set. Você deve ver uma caixa aqui podemos arrastar os ladrilhos do piso. Portanto, encontre ladrilhos dentro do projeto. Então, são pisos sublinhados, ladrilhos, pontos PNG, e vamos apenas arrastar e soltar isso aqui Haverá um pequeno pop-up, que pergunta se você deseja criar automaticamente os blocos, nós fazemos. Então, vamos em frente e nos atingiremos aqui. E então você verá na janela de pré-visualização que todas as peças foram automaticamente divididas em recursos reais de que podemos usar e pintar no jogo Portanto, a maneira mais simples desenhar seria ir ao Tilemap e selecionar individualmente os ladrilhos que queríamos colocar Pressione Q para verificar se você está no modo de seleção. E aqui embaixo na janela do mapa de blocos, queremos estar nas ferramentas de pintura, então isso é D no teclado E então você pode clicar com o botão esquerdo para desenhar o ladrilho. Você pode passar por cima de um, clicar com o botão esquerdo e colocar outro ladrilho no chão. Você verá que, neste momento, o Tap está realmente aparecendo na frente do player. Não é isso que queremos. O que você pode fazer é simplesmente mover o chão até o topo aqui, e isso o classificará automaticamente, forma que o solo fique embaixo do jogador. Então essa é a maneira mais simples de fazer isso. Portanto, embora a seleção das peças , uma de cada vez, funcione, é muito, muito entediante Então, o que provavelmente queremos fazer em vez disso é criar um conjunto de terreno com base nesses ladrilhos de grama e usá-lo para desenhar automaticamente qual ladrilho precisamos, dependendo do que está adjacente a esse ladrilho, se é que existe alguma coisa Portanto, se você expandir o conjunto de blocos no canto superior direito, poderá ir até os conjuntos de terrenos e adicionar um novo elemento Então, vamos deixá-lo nos cantos e lados correspondentes e você expande os terrenos e adiciona um elemento E podemos simplesmente renomear isso, digamos terreno gramado mude a cor para algo um pouco mais gramado, como Agora, na parte inferior, vá para o conjunto de azulejos e depois vamos pintar. Vamos selecionar um dos terrenos do editor de propriedades. Vamos selecionar o conjunto de terreno como conjunto de terreno zero e, em seguida, o terreno que estamos desenhando é grama Portanto, deve ser bastante óbvio quais são os ladrilhos de grama aqui. Mas para que os ladrilhos sejam construídos de forma correta e automática, precisamos selecionar os ladrilhos que deveriam fazer parte desse terreno gramado Então, você pode simplesmente clicar com o botão esquerdo, segurar e arrastar uma caixa ao redor de todos esses ladrilhos de grama, mais ou menos assim. Se estiver destacado, isso significa que está basicamente marcado como parte desse terreno E isso é grama escura aqui. Poderíamos configurar isso mais tarde. OK. E então talvez precisemos trazer esses aqui também. Vamos ver como isso funciona e esses ladrilhos claros estão lá. Agora, esses de baixo parecem mais uma grama escura. Podemos tentar incluí-los e ver no que acontece, mas eles podem não aparecer no corte final do terreno, que pode ter um tom mais escuro de grama Então, teremos que ver como isso realmente funciona. Ok, então selecionamos todos esses ladrilhos como grama. Agora, queremos ir para o canto superior esquerdo e marcar os cantos e lados que são grama ou adjacentes à grama. Portanto, a maneira mais simples de pensar sobre isso com este conjunto de ladrilhos é apenas se a área for transparente, geralmente, você não vai marcá-la, e se for grama maciça ou próxima de grama sólida, você marcará como sendo grama ou grama adjacente. Se eu clicar com o botão esquerdo aqui e arrastar, você verá que está preenchendo o cursor, e queremos que esses oito quadrados que não estão no canto inferior direito sejam marcados como grama porque isso aqui no canto inferior direito está dizendo que há algo mais aqui embaixo O ladrilho no canto inferior direito não é grama e esse ladrilho está refletindo isso Então, ele basicamente usará esse ladrilho quando tudo da direita para a esquerda e esses três cantos forem grama, grama adjacente, mas o canto inferior direito não. Então, a ideia é que você tenha um para todos esses cenários. Então, nesse caso, você faria esses seis ladrilhos superiores, e isso significa que, se não houver grama embaixo deles, no canto inferior esquerdo ou no canto inferior direito, esse ladrilho será atribuído automaticamente Então, só queremos continuar fazendo esse tipo de coisa em todos os sentidos. Portanto, este se parece com todos os cantos e lados, exceto o canto inferior esquerdo. E então esse é o top quatro. Este é, eu acho, exatamente como este aqui de novo, o top oito à direita. E sim, é possível ter vários blocos a mesma máscara, acredito que eles chamam isso de máscara pequena aqui. Então, se descermos até o final, você verá que todos esses são nove ladrilhos quadrados, certeza, porque são todos grama e grama adjacentes. Então, você realmente preencheria tudo isso até o fim. E então isso preencherá tudo dentro desses ladrilhos de borda. Ok, então nós meio que precisamos continuar fazendo isso. Então, este aqui no topo vai ser do meio de cima para baixo, e o direito de cima para baixo. Aqui temos os oito lados e cantos, exceto o canto superior esquerdo. Este é o quarto inferior direito. Este é tudo, exceto no canto superior esquerdo. Os seis ladrilhos inferiores, tudo exceto o canto superior direito, os quatro inferiores esquerdos, tudo exceto o canto superior direito, os seis esquerdos, tudo exceto os quatro inferiores e os quatro superiores esquerdos. Temos nossas peças de canto aqui em cima, e temos as peças sólidas de grama aqui embaixo. Então, para desenhar com ele, basta ir ao Tilemap e selecionar terrenos E o que podemos fazer é pegar essa ferramenta retangular. Deixe-me diminuir o zoom da câmera aqui um pouco. E vamos diminuir o zoom com a roda central do mouse no mapa do jogo, e podemos simplesmente clicar com o botão esquerdo e arrastar uma caixa gigante para o fundo. E aí está nossa grama de fundo. Agora, você verá que esses ladrilhos eram, na verdade, mais escuros. Foi um pouco difícil dizer na minha tela. Então, talvez no conjunto de ladrilhos, também seja grama escura que realmente parecia a mesma para mim. Então, a solução para isso é apenas remover os ladrilhos escuros dos ladrilhos claros ao atribuir a grama Então, se eu clicar com o botão direito do mouse em qualquer uma dessas peças de máscara de bits, ela será removida como parte do ladrilho se removermos totalmente todos os nove lados, cantos e centro. Agora, se redesenharmos isso novamente, não será uma opção quando estiver preenchendo os blocos Então, basta clicar com o botão esquerdo e arrastar outra caixa sobre ela, e aí temos a grama clara e somente a grama clara de toda a cena. Agora, em um jogo tipo Survivor, seu personagem pode se mover muito pelo mapa Então, na verdade, vou fazer disso uma área muito grande. Vamos ir daqui até aqui para que haja bastante espaço para o personagem se movimentar. Agora, você pode ver que realmente demora um pouco para preencher isso porque são muitos blocos. Ok, eu também quero mostrar se eu pressiono E, para ir para o modo Corrida e depois D para a ferramenta de pintura. Em seguida, podemos clicar com o botão esquerdo aqui e você verá que ele atribui automaticamente as peças adjacentes com base no ladrilho no centro Portanto, esse ladrilho não tem ladrilho, então ele reconheceu automaticamente: Oh, eu preciso dos cantos e das peças laterais que atribuímos no terreno E eu posso continuar usando o pincel de borracha assim. E você verá que ele está gerando automaticamente as laterais e os cantos. Pode ter algumas limitações, como precisar ir dois por dois e uma linha para parecer correta verdade, depende do conjunto de ladrilhos, porque existem maneiras diferentes de construir os ladrilhos. Mas, no mínimo, isso é muito, muito mais rápido do que se você tivesse que atribuir manualmente todos esses blocos laterais e de canto. Deixar o computador descobrir por você com base nas regras de terreno que você define, como acabamos de fazer, economiza muito tempo Então, vamos preencher isso. Há também a ferramenta de balde de tinta aqui embaixo, então podemos clicar nessa área em que todos os ladrilhos são iguais. E oh, bem, também temos que E para remover o erasuod. E agora clicamos com o botão esquerdo e tudo é preenchido. Como você pode ver, ele selecionará qualquer região que você esteja procurando. Então isso pode ser tudo isso. Se você quiser preenchê-lo com um terreno de ladrilho totalmente diferente, você pode fazer isso definindo uma terra, mudando para terra aqui embaixo e declarando-a baixa, para que seja um pouco mais avançado do que eu realmente pretendia, mas vamos definir outro terreno com essa terra aqui, o tipo de terra alaranjada para mas vamos definir outro terreno com essa terra aqui, a qual a sujeira pode se transformar um terreno de ladrilho totalmente diferente, você pode fazer isso definindo uma terra, mudando para terra aqui embaixo e declarando-a baixa, para que seja um pouco mais avançado do que eu realmente pretendia, mas vamos definir outro terreno com essa terra aqui, o tipo de terra alaranjada para a qual a sujeira pode se transformar grama. Então, vamos no canto superior direito, declarar um novo tipo de terreno, e eu vou chamar isso Esse marrom está bom, eu acho. Na verdade, talvez você não queira usar, tipo, um marrom em ladrilhos marrons para que seja mais fácil ver onde você definiu e onde não definiu. Mas se funcionar para você, tudo bem. Qualquer cor que você deseja atribuir está perfeitamente correta. Ok, então vamos trabalhar com sujeira de tinta na janela do conjunto de ladrilhos e faremos exatamente a mesma coisa com esses ladrilhos de terra. Então, aqui, estamos pintando os oito superiores esquerdos, não os inferiores direitos, e depois os seis superiores, desse jeito. E eu vou continuar andando por aí assim. Este não é um pouco claro, mas vou usar os quatro no canto superior direito e veremos se funciona corretamente Se quando você realmente desenha com o terreno, ele não parece, você pode ter perdido uma das partes aqui ou ali, você sabe, se está ligada ou desligada, no centro ou nas laterais Então, às vezes, é preciso um pouco de tentativa e erro para acertar. Mas definitivamente vale a pena a longo prazo. Então continue andando, você sabe, da mesma forma. Coloque os cantos e os lados onde está sujo e marque-o como sujo, e depois continue até terminar a volta completa no círculo. Ok, e então termine com as três peças inferiores aqui embaixo. Vamos pegar a sujeira clara e pular a sujeira escura por enquanto Ok, e isso parece bom. Ok, você sabe o que? Eu mencionei que eu ia lidar com a transição da terra para a grama. Mas, na verdade, com esse conjunto de ladrilhos, acho que isso não é necessário porque esses ladrilhos, individualmente, têm menos transparência do que grama aqui ao lado da terra. Então você não precisa definir o terreno gramado individual como parte da terra dessa forma, onde você pegaria esses outros ladrilhos e diria: Ah, isso é grama ali e depois sujeira no canto inferior esquerdo Porque é transparência aqui, então isso realmente não é necessário. Mas em outros conjuntos de blocos, talvez seja necessário fazer isso. Onde, se você sabe que um canto deveria ser grama, então você o marca como grama lá. Portanto, ter dois tipos de terreno para um canto ou lado. Mas aqui, acho que só precisamos de um. Deixe-me dar uma chance e ver como vai ficar. Então eu vou para o Tilemap Vamos limpar a sujeira e tentar desenhá-la. Estou pensando no que realmente precisamos. Ok, então sim, aqui podemos ver que está marcando os lados como transparentes. Eu estou errado. Então, vou tentar marcar esses lados como grama, mas acho que isso não vai realmente nos dar o resultado esperado. Acho que o que precisamos fazer é ter apenas duas camadas separadas para esse conjunto de blocos específico. OK. Então, vou tentar desenhar com isso. Então, mova o modo de mapa de blocos e depois desenhe com terra e vamos tentar isso. Ainda está meio confuso. Vou experimentar uma caixa. Sim, ainda não funciona. Então, desfaça o Controle Z algumas vezes. E o que realmente vamos querer fazer é pintar com terra sobre a grama, ou grama sobre a terra dependendo da camada que você quer colocar no topo. Então, vou clicar com o botão direito na raiz e adicionar um nó filho. Digamos que uma camada de mapa de mosaico. Vou renomeá-lo para , digamos, sujeira. Vou mover isso abaixo do solo para que, por padrão, apareça acima do solo. Então, o que está no fundo está na verdade no topo. Não sei por que está configurado dessa forma. Eu simplesmente sou. E então vamos para a terra. Ah, e queremos reutilizar o mesmo conjunto de peças, a propósito. Então, no chão, vou clicar com o botão direito do mouse no conjunto de blocos e salvá-lo. A propósito, isso está no topo, à direita. Então, salve-o. Localmente no projeto. Assim, posso criar uma nova pasta de conjuntos de blocos e, em seguida, direi ground tileset dot TRs Ok, agora, se clicarmos na sujeira e depois formos até o inspetor, podemos clicar no menu suspenso, Quickload, conjunto Quickload, Ok, agora com essa camada de mapa de blocos, podemos usar os mesmos conjuntos de blocos que já definimos anteriormente É mais ou menos assim que os recursos funcionam em geral. É muito fácil compartilhá-los em vários nós ou várias cenas, etc., compartilhando os recursos dessa forma Ok, então vamos desenhar com terra aqui, e então eu vou desenhar com terra aqui, e você vai ver que a sujeira fica perfeitamente no topo porque estamos pintando em camadas diferentes, então isso só aparece em cima do fundo e há transparência aqui nessas bordas laterais, a grama basicamente preenche as lacunas O outro método que eu estava mostrando, em que todas as informações de textura, como grama e sujeira, estão informações de textura, como grama e sujeira todas em um sprite de ladrilhos seria mais quando você configura vários terrenos em um ladrilho, que é mais complicado, Então, vou renomear o solo para grama. Porque seremos mais específicos lá. Portanto, temos duas camadas de mapas de mosaico, e é muito mais fácil manipulá-las do que seria um mapa de mosaico Ok, vamos ver onde estamos. Provavelmente queremos mais, tipo, desenhar um caminho de terra batida. Ok, então para que a sujeira seja atribuída corretamente, queremos desenhar uma linha de dois por dois. Então, você quer usar a ferramenta retangular ou o teclado Se você fizer apenas uma linha de ladrilho, vai acabar mais ou menos assim. Com base no site do tile, não se sabe como encontrar as informações aqui. Não há ladrilho com transparência na parte superior e transparência na parte inferior, então isso não funcionará. Na verdade, você precisa fazer um caminho de dois pixels de altura como esse e depois arrastar sua caixa, e isso funcionará para isso. Então, poderíamos criar alguns caminhos no nível, mais ou menos assim , você sabe, apenas desenhando dois caminhos com a largura de um ladrilho para onde você quiser. E isso vai torná-lo um pouco mais interessante do que apenas ter um ladrilho de grama simples. Embora dependa totalmente de você como você deseja, você sabe, organizar isso e torná-lo mais interessante. Então, se você já jogou, digamos, Sim City, é exatamente isso que estou fazendo aqui agora, tipo , criando o sistema rodoviário e basicamente colocando-o onde eu quiser. Não vou preencher nenhuma zona residencial em nenhum lugar ou algo parecido. Mas ter mais algumas peças no mapa é um pouco mais interessante do que literalmente apenas grama. OK. Então, vamos ver se isso é bom. Vou clicar em Play. E sim, nosso personagem meio que tem algo em que andar agora, então isso é um pouco mais interessante. 11. Como colocar árvores como objetos cênicos no mapa: E agora acho que seria uma boa ideia adicionar alguns adereços ao nível do jogo Portanto, também temos alguns adereços aqui na pasta do ambiente Portanto, há alguns animados e estáticos. Poderíamos começar com as árvores como o suporte mais simples que podemos colocar no nível do jogo Então, vamos pegar, uh, eu não sei. Vamos clicar duas vezes aqui e você poderá ver os modelos das árvores lá em cima. Então, talvez queiramos pegar essas árvores grandes, e podemos fazer isso com uma amostra do nó Sprite two D. E podemos colocá-los de forma super simples. Tudo o que realmente precisamos fazer é acessar o arquivo PNG e arrastá-lo para a cena do jogo. Ele vai criar automaticamente um Sprite two D aqui em cima Então, basta renomeá-la para Árvore então vamos pegar essa textura, e não vamos desenhar a textura inteira Vamos desenhar uma região dela. Então, o que queremos fazer é usar uma textura de atlas para que possamos selecionar a região que estamos desenhando Então, clique com o botão direito aqui, e eu vou copiar essa imagem bem rápido porque vamos clicar no menu suspenso, ir para a textura do Atlas, que vai remover essa textura temporariamente Expanda isso e clique com o botão direito do mouse e cole a textura que acabamos de copiar no atlas E aí está ele aparecendo novamente. Agora, queremos clicar em Editar região. E então, dentro daqui, vamos para o modo Snap, Cid Snap, roda do meio do mouse para aumentar o zoom, e vamos pegar essa árvore assim, clicar em e vamos pegar essa árvore assim, Fechar e temos uma árvore na cena Ok, agora, dependendo do seu estilo de jogo, você pode decidir adicionar formas de colisão à sua árvore Você faria isso da mesma forma faria com, tipo, um personagem de jogador. Então, se olharmos para o personagem do jogador, você pode vê-lo como uma forma de colisão aqui e fazer com que os objetos colidam com as árvores No entanto, para esta demonstração, queremos minimizar a quantidade de colisões que nossos inimigos farão com qualquer tipo de personagem do jogo Se tivermos muitos objetos colidíveis dentro do jogo e não colocarmos algo como um agente de navegação ou usarmos corpo dois D do personagem para que ele possa se mover e deslizar ao longo da forma de colisão , você fará com que os inimigos fiquem presos Muito mais simples do que isso seria pular a colisão e deixar qualquer personagem atravessar a árvore e deixá-la lá qualquer personagem atravessar a árvore Estritamente para efeitos visuais. Temos a árvore aqui. Vou clicar com o botão direito na cena e criaremos um novo nó para todas as árvores. Então eu vou dizer nó dois D, criar, e vamos mover isso para fora da árvore, então deve ser o submundo E eu poderia simplesmente renomeá-lo para adereços. Vou mover a árvore para dentro daqui. E então podemos simplesmente duplicar essa árvore quantas vezes precisarmos Então, primeiro clique com o botão direito do mouse e salve o galho como uma cena. Vamos colocar a árvore em uma nova pasta, eu acho. Vou ligar para ele. Vamos com Objetos. Sim, e vou colocá-lo aqui dentro . Então, TSN de três pontos Podemos clicar em Salvar N se quisermos editar a árvore, alterá-la para um tipo diferente de árvore e, em seguida, podemos simplesmente entrar na cena. Então, para fazer isso, basta encontrar esse pequeno ícone aqui e abrir um editor, para que você possa editar essa árvore e alterá-la para o que precisar, se quiser alterar todas as cópias dela no mundo. Deixe-me mostrar um exemplo disso. Então, temos a árvore. duplicá-lo várias vezes e, em seguida, pressionarei W para mover as cópias pela cena Então selecione a árvore dois, W, mova-a pela cena. modo de movimento está aqui. O modo de seleção está aqui. Então você precisa selecioná-lo e depois ir para o modo de movimento. E agora eu quero mudar a árvore, todas as cópias da árvore em todo o jogo. Então, vou até a cena da árvore e, aqui à direita, expandimos o atlas, editamos a região e, em seguida, selecionamos essa vermelha Então, árvore vermelha, aperte perto, clique em salvar, e agora de volta ao mundo, todas as árvores são aquele tipo de árvore vermelha com folhas de outono. Agora vou voltar para a árvore e vou desfazer isso Então, vamos pressionar o Controle Z algumas vezes. Vamos escolher a árvore verde padrão. E se você quiser dois tipos de árvores, encontre a cena da árvore em sua hierarquia aqui Então você pode clicar com o botão direito aqui e duplicá-lo. Vamos chamá-lo de outono de árvore e clicar em OK. Abra a árvore de outono com um clique duplo. Vamos ampliar a árvore, pegar a textura e editar a região, e podemos simplesmente pegar essas árvores vermelhas daqui. E agora, se formos para o mundo, podemos colocar as árvores de outono ou podemos colocar a árvore apenas arrastando a cena direto para a cena principal, o mundo Se você se acostumar com isso, poderá preencher a cena rapidamente Agora, uma coisa que eu quero mudar aqui, e talvez eu precise demonstrar para tornar isso óbvio, é que, quando se trata da classificação Y, a posição e a cena da árvore do sprite serão importantes porque vamos classificar em Y a partir da posição central Então, onde quer que o personagem toque o chão, geralmente é onde vamos querer posicionar o sprite Então, aqui nesse estilo de jogo porque eu fiz isso com o jogador, certo? Então, queremos ter certeza de que os personagens estão classificando de onde estão Isso também se aplica aos objetos. Para demonstrar por que isso é um problema, vamos voltar aos adereços da cena principal Eu vou começar a fazer o pedido aqui à direita. D Y Sort habilitado no mundo, faça a mesma coisa. Vá para o pedido e escolha WySort ativado. OK. E agora, se jogarmos e movermos nosso personagem na frente de uma árvore, bem, as câmeras na verdade não nos permitem fazer isso. Então, vamos adicionar uma câmera de acompanhamento para que possamos realmente nos mover um pouco mais pelo mapa. Vou pegar o player, clicar com o botão direito , adicionar um nó secundário , transformar remotamente dois D e, à direita, queremos atribuí-lo à câmera. Queremos atualizar a posição e não a rotação e não a escala, então desmarque-as Ok, agora se apertarmos o play, então pare e jogue. A câmera seguirá nosso player, e essa é uma câmera básica de acompanhamento em Gudo Ok, então chegamos a esse objeto. Se estivermos aqui, você pode ver que estamos nos classificando atrás da árvore, o que seria de esperar Mas se eu for até a metade, agora os personagens estão basicamente na árvore Visualmente falando, ainda queremos que o personagem fique atrás da árvore até chegar aqui. Caso contrário, parece estranho. Então, para corrigir esse salto na cena da árvore, você pode clicar aqui para abrir um editor. E queremos que esse sprite esteja aqui. Mas acho que se você simplesmente mover o sprite dessa forma, porque é o nó raiz, isso não vai consertar nada Então, vamos voltar para o mundo, e sim, vamos clicar em play. Você vai ver o que quero dizer. Vamos até aqui, e isso mudará a posição em que se situa essas árvores, não a posição de onde elas são classificadas, certo? Você vê que o problema ainda está aí? Então, precisamos voltar para a cena da árvore, e eu vou clicar com o botão direito do mouse. Vou adicionar um nó filho, um nó ao qual vou clicar com o botão direito nele e torná-lo a raiz da cena. Então essa é a árvore real na raiz, e agora esse é apenas o sprite dois D. Então, quando você coloca um objeto dentro de outra cena, ele coloca a raiz basicamente em sua posição central. Então, este é o centro do nó D principal raiz, e agora podemos deslocar o sprite Então, se eu pegar esse sprite, bem, ele já está realmente deslocado, mas você pode simplesmente W e movê-lo para onde você precisa Lembre-se de que sua posição de transformação é um deslocamento da raiz, e a raiz é onde ela realmente será instanciada no ponto 00 aqui É por isso que é necessário ter uma base sem dois D e, em seguida, seu sprite aninhado abaixo dela Então, também queremos fazer a mesma coisa com o outono das árvores. Mas você pode notar que, como esses objetos são muito semelhantes, eles estão na verdade repetindo várias etapas Então, o que podemos realmente fazer é ter uma cena herdada baseada na árvore verde do verão onde apenas substituímos a imagem srt, mas todo o resto é o mesmo para aquela Então, vou deletar a cena do outono aqui embaixo. Árvore de outono. Vamos deletar isso. Oh, eu tenho que deletá-lo e fechar a cena. Então exclua isso e, aqui em cima, certifique-se de fechar isso também. Portanto, não economize. E então, no mundo, ele ainda pode ter uma cópia da cena porque não a exclui completamente. Só que agora não há nenhuma cena parental para isso acontecer. Vou cortar isso também e guardar isso. Então, movemos todas as instâncias. OK. E agora, no canto inferior esquerdo, queremos clicar com o botão direito do mouse em Árvore, fazer uma nova cena herdada Portanto, agora temos uma cena não salva com base na cena principal. Podemos salvar isso como outono de árvore e queremos colocá-lo na pasta de objetos. Então guarde isso. E a única coisa que estamos mudando aqui é o sprite. Então clique em Editar região e pegue o sprite para a árvore de verão, clique em Fechar E se voltarmos à cena principal, você verá que poderemos ver o outono da árvore novamente. Parece que eu realmente errei. Portanto, precisamos tornar a textura do atlas única. Caso contrário, você acaba substituindo as árvores. Agora, na cena de outono das árvores, queremos pegar esses dois D brilhantes, e o primeiro instinto que tive foi simplesmente editar a região e alterá-la para esta aqui embaixo Mas isso está realmente incorreto. E deixe-me explicar o porquê. Então, aqui, esse é um recurso de textura, e os recursos são compartilhados entre qualquer cena que faça referência a ele. E tanto nossa árvore quanto nossa árvore de outono estão se referindo ao mesmo recurso Então, se alterarmos suas propriedades, como a região do atlas, assim como a região de edição aqui na cena do outono, ela também atualizará essas mesmas propriedades na cena da árvore original, porque elas estão compartilhando o mesmo recurso Portanto, não é uma nova cópia do recurso de textura. É literalmente o mesmo recurso. Então, queremos clicar com o botão direito do mouse aqui e torná-lo único na cena do outono. E agora podemos mudar isso para essa textura aqui embaixo. Então selecione a árvore de verão e clique em Fechar. Clique em Salvar. Se formos até a árvore verde, você verá que ela ainda tem o sprite da árvore verde. Podemos ir para o mundo. Parece que algumas dessas árvores meio que não foram referenciadas, então talvez queiramos excluí-las bem rápido Então, na verdade, vou pegar adereços e fazer com que seja 00. E então eu quero pegar o nó de adereços e bloqueá-lo Então, se você clicar aqui, poderá bloqueá-lo e, sim, deve impedir que ele se mova. Então, se eu pressionar W e tentar mover o nó de adereços agora, ele não se moverá Então, uma coisa importante a observar é que você tem um nó pai dois D aqui, adereços, toda a posição de seus filhos é na verdade, baseada em relação à posição dos pais Portanto, se você tem um nó de agrupamento como props, mas ainda precisa que seja um nó dois, provavelmente é uma boa ideia bloqueá-lo Então, eu aplicaria a mesma coisa se você tivesse um nó de agrupamento de inimigos ou projéteis, o que provavelmente teremos mais tarde Agora podemos simplesmente adicionar nossas árvores aos adereços, então vou colocar algumas lá Ok, então se eu pegar essa árvore que acabamos de criar e pressionar W e tentar movê-la além do ponto de cimentação, você notará que quando ela chegar aqui, ela simplesmente desaparecerá atrás da grama e da sujeira Então, isso se deve ao motivo da classificação. Então, o que precisaremos fazer é, no canto superior esquerdo, para grama e terra, precisaremos selecioná-las. Acho que você pode até selecionar os dois ao mesmo tempo. E depois vá para o lado direito. Estamos procurando uma ordem, pegamos seu índice Z e o configuramos para algo como, digamos, menos dez, qualquer valor negativo Então, isso fará com que eles estejam sempre atrás de qualquer coisa que tenha um índice Z de zero. Então, se selecionarmos a árvore agora e formos para W e movê-la, agora está corrigido. Sempre aparecerá em cima desses outros objetos. Então, isso é apenas sobre como estamos estratificando nossa cena. Alguns objetos, você deseja classificar com outros objetos no mesmo índice Z, como o caractere na árvore. Mas outros objetos, como o mapa de blocos, devem sempre estar em segundo plano para esses ladrilhos porque os personagens estão no chão, então você deve ver os personagens antes de ver o chão. OK. E agora nós meio que queremos preencher a cena com mais algumas árvores. Você pode simplesmente selecioná-los, duplicá-los e movê-los para cima. Certifique-se de colocá-los no nó de adereços como pais apenas por motivos de classificação E então vamos simplesmente selecioná-los e duplicá-los. Você pode duplicar mais de um por vez. Então, se você quiser um certo padrão, podemos criar um grupo de árvores e copiar tudo isso. Você pode até mesmo movê-los para seu próprio subgrupo, como se fosse um bloco de árvores pai, e então teremos várias árvores diferentes e você poderá ocultá-las para não ter tantos nós de árvores preenchendo Se isso te ajudar. Ok, então vamos mover algumas árvores um pouco mais, e eu poderia simplesmente selecionar todas essas dez árvores. E eu vou sim, vamos tentar o bloqueio que mencionei. Vou clicar com o botão direito do mouse e adicionar um nó secundário. Digamos que nó dois D, bloco de árvore. Vou pegar todas as árvores e movê-las para baixo do bloco de árvores. Então, basta selecionar todos eles. E agora eu poderia salvar essa cena de bloco de árvore no projeto, e nós vamos querer salvar esse bloco de árvore de objetos. Agora podemos simplesmente duplicar o bloco da árvore, controlar D W, movê-lo assim e preencher a cena conforme necessário com árvores onde quisermos Em algum momento, você provavelmente quer personalizar isso um pouco mais, mas acho que essa é uma maneira rápida criar um protótipo da cena, e espero que não pareça muito ruim quando clicamos em Play e ampliamos o zoom Mas sim, se eu estivesse fazendo isso árvore por árvore, isso levaria, você sabe, provavelmente, 20 minutos ou algo assim. Então, se precisarmos fazer algumas personalizações, como aqui, se aumentarmos o zoom, vejo que essa árvore, você sabe, meio perto da estrada, talvez eu queira editá-la para poder pressionar Q e clicar com o botão esquerdo nela Podemos ver que faz parte do bloco três da Árvore. Podemos clicar com o botão direito do mouse na hierarquia e fazer Filhos editáveis E então, para esta, especificamente, agora podemos selecionar as árvores e movê-las. Então, assim, temos mais ou menos um bloco de árvore personalizado. Ok, e podemos esconder isso. Então, agora estamos vendo apenas 15 blocos de árvores em vez de 150 árvores. Podemos jogar, entrar no modo de jogo e simplesmente caminhar pelo nosso mundo de jogo. E a partir desse Zoom In, é muito difícil dizer isso, basta copiar e colar a mesma configuração de árvore umas dez vezes, mas é muito menos chato do que apenas ter Tipo, temos o caminho, temos grama. Se colocarmos algumas flores ou outras coisas aqui, na verdade pode parecer quase um nível de jogo legítimo Ah, e aqui está uma árvore que podemos consertar. Então, você sabe, um pouco de teste de jogo. Você pode encontrar coisas assim. Vamos ampliar e corrigir isso bem rápido. Então, isso faz parte do bloco dois da Árvore. Se você olhar na tela, poderá realmente ver o nome do nó sobre o qual estamos passando o mouse. Portanto, este é o nó pai, aquele em que a cena é Enstus, o bloco da árvore, não seus nós secundários que estão contidos dentro dessa Para torná-lo editável, clique com o botão direito do mouse em Tree Block two, editable Pressione Q para ir ao Modo de Seleção, selecione esta árvore, mova-a e podemos pegar essa também, movê-la para fora do caminho e fazer essas pequenas edições E sim, ao diminuir o zoom, parece que nenhuma das árvores está mais na estrada Então, isso é provavelmente o mínimo do que precisamos que aconteça 12. Adicionando tropeços e fixando a classificação Y: Então, eu estava procurando no pacote Pixel Crawler algumas flores que pudessem ser colocadas ao redor da cena para enfeitá-la um Realmente não vi isso na versão gratuita, infelizmente. Mas acho que temos esses tocos aqui. Podemos tentar usar isso como suporte e preencher um pouco as lacunas e torná-las um pouco menos monótonas Então, vamos pegar isso e criar uma nova cena de toco a partir disso. Então, vou basicamente repetir os mesmos passos com a árvore. Vou arrastar isso para a cena. Vamos para a textura. À direita, clique em Copiar. Então copie essa textura. E então, no menu suspenso, clique em uma nova textura de atlas e, em seguida, vamos colar o atlas Assim. Ok, então você deve ver a imagem inteira. Agora, queremos editar a região e selecionar o toco que queremos usar em nossa cena Então, acho que este tem um toco um pouco menos avermelhado, que parece mais próximo da nossa árvore real Então, vamos fazer essa. Clique em salvar. Agora vou clicar com o botão direito e salvá-lo em uma nova cena. Então, vamos dizer stump dot TACN. Agora, se você se lembra, queremos compensar esse toco Talvez precisemos de qualquer maneira. Acho que, nesse caso , precisa estar alguns pixels abaixo. Então isso significa que precisamos de outro nó, dois D na raiz. Então, clique com o botão direito do mouse em Adicionar um nó filho, nó dois D e, em seguida, clique com o botão direito do mouse e faça disso a raiz. Ok, agora isso é apenas um Sprite dois D. Ok, então a textura do toco é um Sprite dois D, e então a raiz é o Então, agora vamos salvar a cena do toco. Pegue o sprite, pressione W, mova-o provavelmente para a direita para fins de classificação Y. Volte para o mundo. Agora temos o toco Vamos criar mais alguns tocos e criar mais tocos em toda a cena Se acontecer de você selecionar acidentalmente a grama ou a terra, o que você pode fazer é subir até aqui no canto superior esquerdo e bloquear os nós dessa forma E agora você não deveria ser capaz de selecioná-los, eu acredito. Então, se pressionarmos Q e selecionarmos o toco ou ao redor do toco, tudo Portanto, agora esses nós não devem poder ser selecionáveis clicando no mapa Vamos descer até os tocos aqui embaixo. Eles não estão usando essa cena básica correta. Na verdade, vou apenas selecioná-los e excluí-los. E vamos nos livrar do nó dois D também. Ok, pesquise o projeto em busca de tocos. Coloque isso em adereços como esses. Ok, agora vamos diminuir o zoom. Encontramos esse reservatório, aperte W para movê-lo, posicione-o onde quiser Controlei você para duplicá-lo. Ok, agora tem o nome de quando é criado como adereço , então é mais parecido com o que estamos procurando E basta colocar alguns tocos ao redor da cena, você sabe, apenas coisas que você pode encontrar que são mais interessantes de se ver do que apenas grama Claro, o pacote tem outras coisas como edifícios para, tipo, um jogo de artesanato Não achei que fossem os mais apropriados. E se você realmente vai construir prédios, acho que começaria a argumentar que realmente precisa das formas de colisão e, possivelmente, dos agentes de navegação para torná-la mais crível Mas estamos mantendo o mais simplista possível, porque estamos apenas fazendo, você sabe, um jogo muito simples, tipo sobrevivente Acho que já há o suficiente no curso para que, você sabe, eu não queira sobrecarregar ninguém, mas se, no final, você realmente quiser entender os agentes de navegação e os tocos, me avise Eu tenho alguns vídeos no YouTube para esse tipo de coisa. Se você pesquisar o agente de navegação do tutorial Chris, deverá conseguir encontrá-los, se quiser começar com isso. Mas sim, parece uma cena decente montada. Tudo bem, jogue Vamos correr por aí. Nossa cena. Nós temos os tocos. Agora, podemos simplesmente percorrê-lo. Tudo bem. Agora, aqui, isso está um pouco menos certo. Podemos ver que a classificação nessa árvore não está correta. Na verdade, a árvore não está nem um pouco ordenada. Acho que sim, acho que aqui precisamos entrar na cena das árvores de outono e tentar consertar isso. Ok, então vamos para a visão local da cena aqui no canto superior esquerdo. Estamos vendo a cena do outono das árvores. Clique na raiz. E talvez o que precisemos aqui seja verificar por que a classificação está ativada para essa cena, e talvez você precise fazer isso também na cena principal Portanto, a ordenação Y está ativada. Observe que meus jogos ainda estão rodando, então eu posso voltar e ver imediatamente se funcionou ou não. E atualmente, não é. Então, deixe-me ver aquela árvore no mundo. É realmente parte dos pais? Oh, você sabe o que deve ser? São os blocos da Árvore. Ok, então temos que entrar nos blocos de árvores, clicar no bloco de árvore ordenando YSort Ah, sim, quando você cria um novo nível da hierarquia, se você ainda quiser que a classificação Y esteja lá, você deve atribuir YSOrdenabled Então, props ativou o YSorting, mas o Tree Block não. Agora o Tree Block tem. Então, se eu voltar ao jogo, é por que classificar. Ok, então queremos ser capazes de caminhar sobre os tocos e ver se podemos classificar na frente e atrás do toco E, na maioria das vezes, isso funciona. Agora, eu também notei que há um pequeno problema com as árvores. Eles fazem a classificação, ou pelo menos estavam fazendo a classificação, espere Deixe-me verificar com a árvore aqui. Sim, este está funcionando. Mas a posição de onde está sendo classificado está bem errada. Então, o que eu realmente quero fazer é entrar na cena da árvore base para que ela se aplique às duas árvores, e certifique-se de que você esteja na visão local aqui se tiver o jogo rodando no canto superior esquerdo. Selecione o nó Sprite two D porque estamos controlando o deslocamento do Pressione W e, em seguida, mova-a para baixo, provavelmente em algum lugar como lá. Vou voltar ao jogo agora. E então você tenta andar assim, você deve ver que a classificação Y é muito melhor Então, aqui estamos em frente à árvore, como seria de esperar. E então aqui estamos atrás da árvore. Então, isso é muito melhor. Você precisa acertar essas compensações ou as coisas simplesmente não parecerão certas E isso parece ser a maior parte do que precisamos aqui para os adereços de nível Eu também poderia criar um grupo de tocos, então eu poderia pegar esses 16 tocos e dar a eles um Então, vamos clicar com o botão direito do mouse e reverter para um novo nó. E então faremos um nó dois D. Então, agora todos esses tocos foram agrupados em um nó dois D. Vamos chamar isso de bloco de coto Clique com o botão direito do mouse aqui e salve o bloco como sua própria cena na pasta de objetos E agora podemos simplesmente duplicar nosso bloco de tocos, pressionar W, movê-lo pela tela e, você sabe, colocar tocos Portanto, não é exatamente como a geração processual aqui, mas uma ideia semelhante em que estamos apenas tentando preencher o mapeamento com o padrão Dos parâmetros, que basicamente são apenas duplicar as posições dos tocos e depois Então, parece um pouco diferente. E podemos rodar um jogo mais uma vez. Temos a classificação Weiss funcionando muito bem aqui. Talvez para o toco, queiramos alterá-lo em alguns pixels para que possamos entrar na cena do toco E então vamos para a visualização local e moveremos o deslocamento de dois D do sprite para baixo alguns pixels Então, vamos ver como isso é agora. Talvez eu tenha confundido a direção. Na verdade, talvez precisemos fazer mais assim e depois clicar em salvar. Então, estamos aumentando isso. Ok, isso está atrás do toco Isso está na frente do toco. Ok. Sim, isso parece um pouco certo. Portanto, apenas a parte inferior do coto deve estar abaixo do ponto 00 do progenitor E vamos dar uma volta. Sim, vamos ver apenas tocos e árvores. Na verdade, não precisa ser muito variado aqui, porque o foco está apenas no combate e será subir de nível, obter notas e esse tipo notas e Mas ter algo em segundo plano torna tudo mais interessante. Então, eu só queria passar por tudo isso. Obviamente, você pode mover manualmente alguns desses tocos para fora do caminho se eles acabarem na estrada da mesma forma Então, vamos ao mundo, vamos encontrar aquele toco que estava na estrada, ok? Vou pressionar Q, vamos selecioná-lo. Então, vemos o bloco três de Stump aqui à esquerda. Clique com o botão direito do mouse e clique em Filhos editáveis. Em seguida, clique no coto, retire-o do caminho e faça a mesma coisa com qualquer outro toco E aqui está um. Ok, então eu vou selecionar esse nó, Stump block two. Seremos crianças editáveis Em seguida, clique no coto individual, W para movê-lo, mova-o para fora do caminho e pronto Ok, também podemos fazer isso com essa árvore aqui em cima. Então isso faz parte do bloco cinco da Árvore. Vamos torná-lo editável. Selecione a árvore e mova-a. Oh, tem outro aqui. Interessante Na verdade, devo ter duplicado um bloco de árvore no mesmo local Sim, certo. Vamos passar por aqui. Tudo bem Ok, eu realmente não vejo nenhuma outra árvore na estrada. Há um toco aqui, então vou tentar consertá-lo também. W para movê-lo, tire-o do caminho. Torne o pai editável, se necessário. E isso provavelmente vai ficar quase tudo bem. Um último. Crianças tão editáveis. Então, selecione-o. Torne o pai editável, selecione o nó individual e retire-o do caminho. E é basicamente isso. Portanto, reduza tudo, para que não sobrecarregue sua hierarquia Essa é uma das razões pelas quais eu criei o prop node, para começar Hum, se você tivesse, tipo, texturas de flores ou outros rabiscos, talvez pedras, você provavelmente os colocaria em uma camada separada de pedras ou rabiscos aqui em cima e apenas os posicionaria em um índice Z que é mais alto do que Essa seria uma boa maneira de começar com isso. Como alternativa, eles podem ser seus objetos individuais vistos. Mas não tenho certeza sobre o desempenho. Eu diria que, se for parte do mapa de blocos, provavelmente é muito melhor do que se eles fossem, você sabe, seus próprios nós na cena do jogo. Mas, desde que você não tenha muitos, provavelmente não é um Um, então essa será basicamente nossa parte de mapeamento de blocos do curso nossa parte de mapeamento de blocos do E a partir daqui, podemos simplesmente começar a montar armas e inimigos, ganhar experiência, subir de nível, HP, todos esses recursos do tipo a montar armas e inimigos, ganhar experiência, subir de nível, HP, RPGSh rogue 13. Projéteis gerados com um cronômetro: O personagem pode se mover. uma espécie de mundo de jogo para jogar. Em seguida, o que precisamos fazer é criar um ataque com um cronômetro que criará um projétil onde possamos usá-lo para atacar inimigos sem precisar nenhuma outra entrada importante do Em jogos de sobrevivência, você normalmente acaba acumulando várias armas diferentes, e elas são acionadas automaticamente para A única coisa com que você precisa se preocupar é andar pela tela e deixar as armas trabalharem enquanto evita os inimigos. E esse é basicamente o ciclo de jogo. Então, comece com isso. Vamos criar nosso script e player de armas. Então, nesta cena em dois D, vou clicar com o botão direito na raiz. Vamos adicionar um novo nó filho D, nó dois D aqui. Vou renomear isso para arma, vamos clicar com o botão direito do mouse e anexar um script para ser arma DotGD E isso pode ir para a pasta do player por enquanto. Então, vamos ter esse script de armas. Podemos até mesmo fazer dela a arma 2 D, honestamente. Então, se quisermos entrar no sistema de arquivos, podemos renomeá-lo para arma dois D, se isso fizer mais sentido Ok, então o que esse script de arma em dois D precisará para criar os objetos de jogo de projéteis que na verdade, são a representação em dois D da arma no mundo do jogo que pode danificar um inimigo é que precisaremos de um cronômetro Então eu vou dizer var timer do tipo timer. Agora, você pode adicioná-los diretamente no inspetor de cena aqui à direita, como você adicionaria outros nós Mas eu não quero ter que fazer isso para cada script de arma que eu crio. Então, para tornar isso um pouco mais rápido e fácil, direi que a função de sublinhado está pronta Então, quando nosso script estiver pronto, pegaremos a variável do cronômetro e a definiremos como um novo cronômetro Bem, adicione o cronômetro como filho, então adicione o cronômetro infantil Isso significa que esse novo cronômetro existirá sob a arma Se removermos a arma, também removeremos o cronômetro E então queremos nos conectar ao sinal do cronômetro. Portanto, o cronômetro tem um sinal de tempo limite, e queremos conectá-lo a uma função, uma função que pode ser chamada, para que possamos dizer “tempo limite de tempo E aqui embaixo, podemos funcionar no tempo limite do cronômetro. Agora, esse tempo limite do sinal na verdade não envia nenhum dado, então não precisamos de parênteses E então essa função terá um tipo de retorno de vazio Então, quando o tempo acabar, queremos basicamente lançar nosso feitiço Queremos invocar os projéteis. Então eu acho que cast é um bom nome para essa função. Então, vamos apenas dizer lançar, e queremos passar na direção que nosso projétil será lançado Então, se estivermos voltados para cima, vamos lançar para cima. Então, podemos obter uma referência para a direção voltada para isso, mas voltaremos a isso em um segundo. Então, teremos uma função convertida, e isso tomará a direção P do vetor dois, a direção em que estamos lançando, e podemos retornar vazio para isso Portanto, para que o sinal de tempo limite seja atingido, precisamos primeiro iniciar o cronômetro. Então, diremos que o timer dot start. Então, o tempo que queremos configurar por quanto tempo até criarmos uma instância de projétil dependerá da definição de cada arma de projétil Mais tarde, teremos diferentes níveis de armas, então podemos realmente mudar o resfriamento à medida que o nível da arma sobe para que possamos atirar com mais frequência seria uma forma de fortalecermos nosso personagem. Para a arma dois D, vamos querer ter essa definição como um recurso que possamos usar para que nossa arma saiba como operar. Então, vamos exportar VR e, digamos, a definição da definição do tipo de arma, e precisaremos criá-la. Então, no sistema de arquivos, vamos expandir para fora e, em seguida, vou criar uma nova pasta para nossas armas Então, vou clicar com o botão direito do mouse nos recursos e fazer Criar novas armas de pasta. E dentro dessa pasta, vou criar um novo recurso. Então, clique com o botão direito em Novo recurso. E vamos criá-lo como um recurso básico por enquanto. Eu vou dizer definição de lança. Como nosso personagem é um ragonte daremos a ele uma lança como arma padrão Então, vou salvá-lo aqui, Script, precisamos criar nossa nova definição de arma. Então, vamos clicar com o botão direito nas armas criar um novo script. Digamos que a definição de arma no momento seja herdada do recurso e a criará Então, agora vamos para a definição da arma. Vamos dar a ela o nome da classe, a definição da arma. E aqui é onde vamos definir as estatísticas nas especificações da interface, como o nome de como nossa arma é representada em um formato de dados, mas não no mundo do jogo Isso será mais da classe de projéteis, que se estende do nó ao D. Então precisamos de alguns aqui para juntar tudo Eu diria que o sistema de armas é provavelmente a parte mais complicada, então vou tentar examiná-la minuciosamente. Então, primeiro, talvez queiramos definir um nome. Então, em export var name. Portanto, os nós, por padrão, têm uma propriedade de nome, mas os recursos não. Portanto, podemos tirar proveito disso definindo um nome de string personalizado. Então esse será o nome de exibição, como representamos na interface do usuário. E então poderíamos dizer no ícone export var do tipo textura dois D. Mais tarde, adicionaremos blocos de estatísticas personalizados para cada nível de arma, mas isso é demais para este vídeo Então, por enquanto, o que precisamos daqui pode ser algo mais parecido com uma função de resfriamento, e podemos passar de um nível aqui porque, na verdade, não sabemos que nível a arma está a partir da definição da arma. Isso será definido na arma de tempo de execução, dois objetos D aqui. Porque isso sobe de nível no jogo. E então a definição é mais uma definição de editor. Ele configura como a arma opera em cada nível. Então, essas são coisas separadas. O nível da arma está em D. Então, queremos passar o nível em que ela está atualmente. Então, poderíamos dizer, nível P, e isso vai ser um número inteiro Devolveremos uma bóia para esfriar a arma. Então, por enquanto, vou simplificar isso e, digamos, se você virar um ponto. Posteriormente, podemos torná-lo mais personalizado resolvendo o resfriamento com base no nível que passamos Mas basta simplificar aqui para que possamos testar se tudo que a arma dois D realmente funciona. Então, na arma dois D, queremos iniciar o cronômetro em, digamos, ponto de definição Get Cool Down. E vamos simplesmente passar digamos, menos um aqui porque pretendemos alterá-lo. Então, estou colocando uma pequena nota aqui para me lembrar de obter o nível real, apenas uma nota para que, você sabe, uma vez que testemos isso, possamos continuar a partir daí e implementar totalmente o sistema. Ok, também vamos querer conseguir a instância do projétil que estamos tentando criar Então, vamos fazer uma função get scene. Também podemos passar de nível. Isso retornará uma cena lotada. Vamos criar essa cena de arma, o projétil, mais especificamente Então, em duas visualizações em D, vamos adicionar uma nova cena. Vamos criar uma cena em dois D aqui. Vou renomear isso para Spear. Vamos clicar com o botão direito do mouse nele, anexar um script, e esse será o ponto de projétil GD Eu provavelmente quero salvar isso e, oh, digamos que a pasta de armas. Eu acho que isso faz sentido. E, em seguida abra Criar, isso é cancelar. Create está aqui, e então queremos dar a ela o nome de classe projétil, e salvaremos o spear dot TSCN dentro das armas para que possamos realmente Queremos anexar um Sprite a ele. Clique em Spear, anexe um nó Sprite two D e, em seguida, vamos pegar a arma Que fará parte de uma textura de atlas aqui no canto superior direito Então, faça uma textura de atlas. E então vamos carregar rapidamente nosso projeto. Acho que foi 16 por 16. E então precisamos obter nossa textura. Então vá para a arte no canto inferior esquerdo. Vá para Pixel Crawler, vá para armas, madeira E então a palavra ponto PNG, nós a colocamos no slot Atlas Ok. E agora podemos editar a região, ampliar e queremos a lança, que está aqui Então, vamos arrastar isso e clicar em Fechar. Ok, agora temos o sprite da lança. Assim, podemos pelo menos ver nosso projétil no topo do jogo quando ele estiver basicamente carregado Queremos incluir essa cena. Vamos voltar para o jogador, e eu vou abrir o script da arma. Em seguida, vou clicar com o botão direito do mouse na definição da arma e no símbolo Loup. E para obter a cena, simplesmente faremos algo como retornar a carga. E agora queremos carregar a cena da lança. Então cuspa o ponto TSN. Você pode ver que você pode simplesmente encontrá-lo nos recursos weapons spit dot TSEN e colocá-lo lá Então, mais uma vez, essa é uma medida temporária apenas para simplificar para que não precisemos implementá-la totalmente. Então, em nossa arma dois D, quando lançamos, vamos fazer com que essa arma seja vista a partir da definição. Então, queremos dizer var, projétil será do tipo projétil, e vamos definir isso igual à definição Get SN e vamos dizer menos um aqui para o nível. Você sabe o que? Na verdade, poderíamos começar a declarar nosso nível real da arma Então, vamos fazer disso um nível um. Eu direi no nível export var. Esse será um tipo de número inteiro e começará em um Ok, agora podemos simplesmente passar o nível para essas funções, nos acalmar e ser vistos. Ainda não faz nada com isso , mas pelo menos o temos lá. E, claro, quando aumentarmos o nível de nossa arma, aumentaremos o nível aqui em um, e isso mudará o que essas funções nos devolvem se tentarmos esfriar ou pegar a cena Ok, então nós pegamos a cena, e então queremos instanciar nela Então, queremos adicioná-lo quando criança ao nosso grupo de projéteis e à cena principal Onde estamos fazendo com que o nodo realmente gere os projéteis Vamos ver o cenário mundial em duas vistas em D, e vou minimizar isso. Vamos clicar com o botão direito do mouse em Mundo e no canto superior esquerdo e adicionar um novo nó dois D. Vou apenas renomear esses projéteis Agora vamos para o canto superior direito e vou usar grupos aqui. Vamos atribuir um grupo ao nó de projéteis. Então, adicione um novo grupo. Vou apenas fazer projéteis em letras minúsculas, torná-los globais, e vou dizer o nó em que todos os projéteis estão contidos Ok, agora podemos ver se o nó de projéteis tem esse grupo, e podemos referenciar o nó fazendo primeiro no grupo Então, vamos voltar ao roteiro. É o sublinhado dos projéteis. Também podemos declarar isso como uma constante, se quisermos. Então, eu diria que um grupo de projéteis constantes, tornando a constante em maiúsculas a convenção padrão Isso deixa claro que esse é um valor constante que não vai mudar e se diferencia de uma variável normal, como nível ou definição, que pode mudar durante o jogo Então, vamos definir isso igual a projéteis minúsculas, assim como Então, vamos querer pegar esse nó e adicioná-lo a esse nó. Então, vamos armazená-lo em cache. Como variável local, digamos var projectiles parent, e isso será um nó Então, para preparar isso, vamos fazer isso antes do cronômetro. O pai do projétil sublinhado é igual ao nó G. Mas temos que pegar a árvore primeiro. Então, pegue o ponto da árvore, obtenha o primeiro nó e o grupo, e queremos o grupo de projéteis, que é um nome de string Na maioria dos casos, strings e nomes de strings podem ser usados de forma intercambiável Ele se converte entre os tipos automaticamente em muitos casos na parte de trás Podemos declará-lo como um nome de string aqui porque é isso que ele espera disso Então, obtemos o primeiro nó do grupo. Se isso não existir, provavelmente teremos um erro no console, o que é bom. Então, só precisamos ter certeza de que nossos níveis de jogo realmente tenham um nó de projéteis como esse Se quiser, você pode salvar esse nó em seu projeto e reutilizá-lo, clique com o botão direito do mouse em Salvar cena de ramificações e, em seguida, talvez criemos uma pasta de níveis Para qualquer coisa relacionada aos níveis coloque os projéteis pontilhem o TSC aqui Então, se você continuar reutilizando-o a partir daqui, eles sempre estarão nesse grupo de projéteis e, basicamente, você não deveria dessincronizá-lo dessincronizá-lo Então, agora você pode reutilizar a cena dos projéteis sem se preocupar com a mudança de valores entre os níveis em que você os usa, então isso pode ser um E agora, depois de criarmos o projétil, queremos ter certeza de que ele seja adicionado como filho ao projétil pai Então, sublinhe os projéteis, projéteis de pais e filhos. Assim. Nós podemos nos livrar disso agora. E então só queremos ter certeza de que a posição global é igual à posição global da arma dois D. Então, digamos que a posição global do projétil seja igual à posição global aqui Então, estamos assumindo a posição do nó D da arma dois. E então precisamos passá-la em direção ao elenco. Então, vamos fazer o vetor de dois pontos, certo? São maiúsculas. Um valor constante. E agora o script deve poder ser executado sem erros. Ok, então tem a cena. Eu sei qual tempo de recarga definir. E sabe criar uma cópia do projétil em cima do nó D da arma sempre que o cronômetro passar Então, vamos fazer isso e tentar. Podemos ver o tempo de recarga e o valor nulo. Então, na verdade, não definimos a definição da arma. Então, poderíamos dizer, afirmar que a definição não é igual a nula Portanto, cada arma requer um conjunto de definições de arma. Então, precisamos ir até o jogador. Precisamos encontrar esse nodo D da arma. Vou renomeá-la como arma dois D. Vamos até o inspetor no canto superior direito e, em seguida, definir nossa definição de arma Então, nova definição de arma, expanda isso. Possivelmente vamos querer o ícone e o nome. Então eu vou chamar isso de lança. E vamos pegar o ícone da cena da lança. Então, podemos simplesmente pegar o mesmo sprite e copiá-lo para o ícone Então, vou clicar com o botão direito na textura. E copie. Agora vamos para a cena do jogador em que temos definição da arma definida, clique com o botão direito do mouse no ícone e cole nele. Ok, então aqui está nossa representação da lança na interface do usuário. Então, clicamos em Play e colocamos a lança na instância a cada 1 segundo Agora nosso projétil ainda não se move. Ele não tem código para se mover, mas temos tempo para colocar os projéteis no mundo na hora certa, com base em nossa classe de definição de arma Claro, há muito mais do que isso. Ainda não mexemos com as estatísticas nem nada, mas esse é um bom começo Então, vou falar mais sobre isso na próxima 14. Mova os projéteis na direção do lançamento: Então, neste momento, estamos prontos para começar a colocar inimigos no jogo e, em seguida, fazer com que nossos projéteis capazes de atingi-los se movendo pela tela Ok, então vamos fazer com que nossos projéteis possam se mover agora na direção em que foram lançados Vou até a cena da lança, e esse é o projétil da lança, aquele que realmente aparece no mundo do jogo Vamos abrir esse script. E vamos querer colocar uma função de lançamento aqui para que, quando nosso projétil for instanciado, outro script possa dizer em que direção ele se moverá Então, vou colocar a função launch e vamos passar em uma direção. Então P sublinha o vetor de direção dois, e essa será a direção em que os projéteis se moverão Então, queremos pegar essa direção de lançamento e torná-la local para que possamos usá-la em nossas funções de processo, o processo será atualizado a cada segundo e traduzir nosso nó de projétil pela tela Então, a direção var será o vetor dois, e vamos configurá-la aqui mesmo no lançamento. Portanto, a direção é igual à direção P. Agora, quando lançamos um projétil, também queremos colocá-lo na fila para liberado após um certo período de tempo Caso contrário, projéteis que nunca atingissem um alvo existiriam no mundo do seu jogo para sempre e acabariam por causar problemas de desempenho Portanto, queremos garantir que os objetos sejam libertados eventualmente. Então, podemos fazer isso esperando um certo período de tempo. Eu vou dizer espere. Então, isso basicamente significa que ele voltará para o resto do código que segue essa linha depois que a condição for atendida. Então, vamos dizer: pegue uma árvore. Então, estamos obtendo a árvore de cena atual na qual esse nó de projétil existe e, em seguida, criaremos o cronômetro E nós damos um tempo. Então, digamos que 1,0 segundo. Tudo o mais você pode deixar como padrão. Então, tudo isso significa que estamos aguardando o método de tempo limite no cronômetro que criamos usando a árvore de cenas e esperamos um segundo para que esse tempo limite ocorra E então, uma vez feito isso, podemos colocar apenas um quarto no nó do projétil Isso vai liberar o projétil em qualquer coisa abaixo dele. Agora, um projétil que atinge alvos, se atingir um alvo, provavelmente se removerá antes disso, mas isso é apenas uma alternativa para que, se errar completamente todos os inimigos, acabe se libertando que, se errar completamente todos os inimigos, acabe se libertando Ok, e então precisamos que o projétil realmente se mova. Então, digamos que o processo de sublinhado de função ou processo de física, na verdade, seja provavelmente um pouco mais apropriado Vamos fazer isso. Então, geralmente você usa o processo de física para qualquer coisa que envolva mover objetos físicos pelo jogo. Agora, este é um nó dois D. Não estamos adicionando nada parecido física de corpo rígido ao projétil, mas apenas para que seu movimento se sincronize com todo o resto do sincronize com todo o resto Se o processo físico for definido para 60 vezes por segundo ou 60 períodos de movimento por segundo , ele se moverá 60 vezes por segundo, apenas para mantê-lo consistente com todo o resto do. Exporte a velocidade var aqui na parte superior do tipo float. Vamos adicioná-lo a 100. Então essa será apenas a velocidade padrão do projétil. Então, coisas como a velocidade e a duração que esse projétil dura no mundo do jogo são estatísticas que eu quero extrair em um script de estatísticas separado para que possamos defini-las por arma e por nível de cada arma de uma forma muito mais organizada Mas, por enquanto, é bom o suficiente, então trabalharemos nisso mais tarde. Então, queremos dizer traduza aqui. Qualquer nó TD pode ser traduzido pela tela. É um movimento sem qualquer colisão. E vamos dizer que estamos nos movendo na direção vezes a velocidade, vezes o Delta. Agora, se você quiser saber o que isso calcula quando você está depurando, atingindo um ponto de interrupção, talvez queira fazer algo mais parecido com movimento Var, que é um vetor dois, será igual a esse bit aqui, Controle X, cole essa extremidade ali e, em seguida, basta traduzir o movimento. Agora, se você atingisse um ponto de interrupção, aqui mesmo, e talvez pudéssemos fazer isso apenas pressionando play, porque o processo físico será acionado assim que esse espírito for criado, podemos ver na parte inferior que temos o valor do movimento de 00 e Y é zero, zero, porque não lançamos o projétil com essa função, então ele não tem realmente pressionando play, porque o processo físico acionado assim que esse espírito for criado, podemos ver na parte inferior que temos o valor do movimento de 00 e Y é zero, zero, porque não lançamos o projétil com essa função, o que o padrão é o vetor dois pontos zero no momento Ok, então eu vou desfazer o ponto de interrupção. Você. Ok, então feche o jogo. Na verdade, isso traz um bom ponto que quero abordar, que é que se a direção for o vetor 20, isso provavelmente representa um problema, porque sempre lançamos na direção em os personagens estão voltados, que nunca deve ser o vetor dois pontos zero. Portanto, podemos esperar que a função de inicialização já tenha sido chamada antes de colocá-la totalmente em cena com Adhild Então, vamos preparar o sublinhado dessa função. E vamos afirmar que a direção não é igual ao vetor 20 Chame o lançamento para definir a direção ou projétil antes de adicioná-lo à criança Então, queremos exigir que já tenhamos definido a direção com a função de lançamento e observe que devemos chamar o lançamento antes de chamarmos Add hild Então, a prontidão ocorre depois de ok. Agora, se eu correr, devemos imediatamente clicar na afirmação , conforme esperado Então, vamos entrar no script D da arma 2, onde adicionamos o filho do projétil pai Então, agora queremos chamar o lançamento do ponto do projétil na direção P que passamos para a função de lançamento Para que ele realmente o configure para algo adequado. Agora, podemos ver que aqui embaixo, no tempo limite do vetor, estamos usando o vetor de dois pontos à direita Então eu acho que seria uma boa maneira de testar. Nesse caso, ele deve sempre se mover para a direita. Então, o problema aqui é que nosso lançamento está tentando fazer duas coisas distintas. Acho que na verdade faz mais sentido colocar essa parte na função ready, já que a estamos usando agora. Então eu vou colar isso lá, Controle X, isso, controle V, colar . Isso faz sentido. Assim que o projétil estiver pronto, nós o preparamos para ser liberado após um determinado período de tempo Portanto, isso mantém o método de inicialização lidando apenas com uma coisa, que é basicamente inicializar o objeto depois de criado Então, essa é quase certamente a melhor maneira de fazer isso. Ok, agora vamos clicar em play. E temos nosso projétil disparando para a direita. Você também pode ver que eles duram apenas 1 segundo, provavelmente não o suficiente, mas é um bom teste para ter certeza de que estão realmente se liberando Então, neste momento, haverá apenas uma ou duas lanças na cena a qualquer momento Isso não deve causar nenhum problema de desempenho. 15. Configurando inimigos e Hitboxes: Nossos projéteis se movem para a direita. Agora, vamos criar um inimigo para que nossos projéteis possam realmente se conectar a ele e atingi-lo Então, isso significa que estamos configurando uma caixa de acerto e uma caixa de dor neste vídeo, e nos preocuparemos com estatísticas mais tarde, como a HP. Então, no meu projeto agora, vejo na parte inferior, que há alguns avisos aqui Eles estão apenas mencionando que, se você não estiver usando um parâmetro, você deve sublinhá-lo Então, vou clicar em cada um deles e dar um pequeno sublinhado Então, eu não estou usando o Delta neste processo de física do jogador. Então, eu destaco o Delta. Isso implica que não está sendo usado. E então aqui em outro roteiro, eu vou fazer a mesma coisa. E apenas para qualquer um desses avisos que você está recebendo, basta repetir Você não está usando o parâmetro e, em seguida, sublinhe-o para indicar que você espera não usar o parâmetro e que isso não é um acidente ou um erro E vamos seguir em frente e criar nosso primeiro inimigo. Então, vamos começar com um Oc. Vou criar uma nova cena aqui no topo, e vamos para duas cenas D à esquerda. Vou renomear isso para Oc. Vamos clicar com o botão direito, mudar o tipo para um corpo de personagem dois D. E selecionar isso. Ok, então eu quero clicar com o botão direito do mouse no orc e adicionar um nó filho Vamos fazer um sprite TwoD aqui. Além disso, clique com o botão direito aqui e adicione uma forma de colisão infantil. E à direita, vamos fazer disso um pequeno círculo, mais ou como o que você fez com o jogador. E vamos controlar, salvar a cena dentro dos personagens. Vou criar uma nova pasta para os inimigos. Então, inimigos, coloquem isso lá e salvem o TAC da orca Ok, agora nosso orc precisa de Bright, é claro. Então, vamos selecionar esse nó britânico e desceremos para o canto inferior esquerdo Vamos procurar, acredito que foram entidades, multidões, tripulação de orcs, e queremos pegar uma dessas Então, eu estava apenas usando o orc padrão para que pudéssemos pegar a folha ociosa Vou selecionar esse nó Bright two D e, à direita, vamos arrastar e soltar essa folha ociosa aqui Está bem? Agora, obviamente, temos uma configuração semelhante à do player em que temos uma folha de sprites Precisamos definir quantos quadros H são da esquerda para a direita, que você pode ver que são quatro. E queremos fazer isso com um reprodutor de animação. Então, vou clicar em Ok, adicionar um nó filho. Player de animação. Então selecione o player de animação, desça até o final, faça uma nova animação do Idol. Ok, e precisamos estruturar algumas das propriedades do sprite Então, vamos adicionar uma faixa, uma faixa de propriedades, sprite de dois D e vamos procurar quadros H. Então, clique duas vezes nele. Ok, e então repita as etapas para faixa de propriedades, sprite dois quadros D, V, trilha de propriedades, sprite duas texturas D. E no canto inferior direito, habilite o encaixe aqui e altere o tempo de encaixe para 0,1 segundos Então, um quadro por décimo de segundo. E, por fim, à direita, queremos alterar isso para 0,4 segundos de duração total e ativar o loop OK. Na linha do tempo aqui, volte para o início da animação, clique com o botão direito do mouse em inserir uma chave Então, temos nossos quadros H. Queremos pegar isso e, no canto superior direito, mudamos para quatro. E, em seguida, vFrames, queremos inserir uma chave. Deixamos isso como um aqui em cima. Clique com o botão direito do mouse para inserir uma moldura. Então esse será nosso primeiro quadro. Não se preocupe em mostrar todos os quatro quadros de uma só vez, o que será corrigido automaticamente em um segundo. Em seguida, queremos clicar com o botão direito do mouse e inserir uma chave para nossa textura, que você pode ver no canto superior direito que já está usando nossa animação como padrão Então, ainda não reproduzimos a animação, então ela ainda está mostrando quatro quadros, mas assim que eu jogar, ela mostrará o primeiro quadro da animação ociosa, e a seção de quadros aqui embaixo é atualizada automaticamente de acordo com o que esperávamos Então, agora queremos ir para 0,1 segundos. Ele deve encaixar em intervalos de 2,1 segundos e, em seguida, clicar com o botão direito do mouse e digitar a tecla por quadro e, em seguida, alterá-la no canto superior direito para uma aqui em cima Então esse é o segundo quadro da animação. Em seguida, adicione o valor do quadro de dois, que é o terceiro quadro aqui e o último quadro de valor três, que representa o quarto quadro da animação. Ok, agora, se estamos jogando, devemos ter nossa animação inativa E para um personagem simples, parecido com um sobrevivente, só vamos colocá-lo voltado para a esquerda e para a direita Então, precisamos apenas de um nó giratório nessas animações individuais para saber se ele está voltado para a esquerda Então, como isso é para um jogo simples de sobrevivente, só o temos voltado para a esquerda e para a direita Então, precisaremos apenas adicionar um nó giratório posteriormente. Além disso, precisamos apenas de nossas animações de corrida ociosa e morte E é basicamente isso, a menos que um personagem precise de uma animação de ataque especial. Então, vamos duplicar a animação ociosa e colocar nossa animação de execução Para animação de execução, queremos colocar a textura aqui embaixo e alterar o valor e o canto superior direito da planilha de execução. Então corra e arraste para o canto superior direito. OK. E são seis quadros de animação. Então, queremos pegar os quadros H aqui e alterá-los para seis. E então queremos adicionar o quadro cinco e o quadro seis aqui. Então, a chave muda esse valor e o canto superior direito para quatro, insere uma chave, altera esse valor para cinco e, em seguida, pega a duração da animação de execução e faz com que seja de 0,6 segundos, aperta play, e devemos ter nossa animação de execução. Agora, acho que está compensado incorretamente, menos como era o ídolo da corrida do jogador Então, precisaremos fazer essa configuração de deslocamento também. Então, vamos ao ídolo. Vamos mover esse personagem para cima. Certifique-se de selecionar especificamente o nó do sprite. Em seguida, pressione W para ir para o modo de movimento e mover o sprite para cima , de modo que o ponto 00 fique centralizado em seus pés aqui embaixo Onde quer que esteja, deve estar o centro de gravidade onde toca o solo Em seguida, vá para transformar à direita e insira um quadro-chave Portanto, tenho 14 pixels negativos como posição Y. Quadro chave: clique Criar e apenas reinicie a faixa. Tudo bem. E agora também precisamos estruturar o keyframe da execução. Então, para correr, vamos para o canto superior direito, e eu vou fazer isso. Vamos tentar 27 pixels negativos. Vamos tentar 30 pixels negativos. Achei que eles estão configurados da mesma forma que o jogador, o mesmo artista e tudo mais. Então, vamos estruturar isso E crie. E temos nossa animação de corrida. Agora, vamos mudar rapidamente para o Idol. Ok, agora temos nossa animação de corrida sendo reproduzida. Vamos mudar rapidamente para o modo inativo e ele jogar. E parece que os pixels se alinham. Teremos que testar esse final de jogo, é claro, se quisermos realmente mostrar a animação de Idle Nesse caso, porém, talvez nunca mostremos a animação de Idle, a menos que o inimigo pare de correr em direção ao jogador Mas a ideia, pelo menos com essa configuração, será que o inimigo esteja sempre correndo em direção ao jogador enquanto o jogador existir. Portanto, talvez nunca vejamos realmente a animação ociosa. Dependeria de você. Talvez quando o jogador for derrotado, os personagens simplesmente comecem a ficar inativos em vez de se moverem mais na tela porque não há mais jogadores para lutar Mas isso seria apenas um extra que não é realmente necessário. O que precisamos, porém, é a animação da morte. Então, vamos correr porque acho que a animação da morte tem seis quadros, e vamos duplicar isso para fazer uma animação de morte , então digite Death Enter Vamos desligar o loop para isso. Os personagens morrem apenas uma vez. Em seguida, queremos pegar a textura e alterá-la para a folha Death Sprite no canto inferior esquerdo Arraste isso para o inspetor e vamos clicar em reproduzir lá. E então, se mudarmos para inativo, parece que ele se alinha e a execução parece que está alinhada Ok, então isso provavelmente é bom. Acho que a posição sobre a morte é menos 30. De qualquer forma, temos nosso Oc. Podemos simplesmente colocar um orc no mundo do jogo. Então, vamos pegar o orc aqui. E, na verdade, provavelmente queremos a hierarquia de inimigos, então vou clicar com o botão direito do mouse para inserir um nó Então, no segundo nó D, vamos matar inimigos ou até mesmo ser NPCs, se quisermos Talvez inimigos sejam melhores. E eu vou derrubar um orc do canto inferior esquerdo. Sob os inimigos. Então, podemos ver que ainda não está exibindo a animação. Então, vou clicar em Abrir e editar, e vamos ver o que está acontecendo com isso. Provavelmente precisamos, tipo, definir uma animação padrão. Então, eu poderia pegar a morte e transformá-la em ociosa. Vamos defini-lo como inativo. Está bem? Clique em play. Vamos voltar ao mundo do jogo. Isso resolve isso? Acho que não. Ok, então como isso não está funcionando, devemos ir para o reset. Animação. Então, sempre que você não está reproduzindo uma animação, ela é redefinida para esses valores E podemos ver que os quadros de He aqui, se olharmos no canto superior direito , estão, na verdade, definidos como um. Então, se definirmos isso para quatro, e acho que agora clicamos em play no reset, então é isso que devemos ver se voltarmos ao mundo do jogo. Então salve sua cena de orc, vá para o mundo do jogo e tudo bem, agora está tudo certo Então eu vou pressionar W e mover o c. Ok, e então vamos apenas Controlar D, duplicar mais alguns cs E então eu acho que a última coisa que queremos fazer aqui é pegar os inimigos e habilitar o Order y Sort. Como isso é evidente para todos os orcs, queremos que os orcs também se classifiquem uns com os outros Isso pode ser necessário. Então, isso pode ser necessário para colocar lá. Ok, então nossas lanças podem se mover, mas na verdade não podem atingir nada Não montamos uma caixa de ataque e nossos orcs podem existir, mas eles não têm uma caixa de HRT para realmente sofrer danos Então, as caixas HRT e as caixas de sucesso e Gadot D serão os Ds da Área dois Se você vem da unidade, seria mais como uma zona de gatilho. Vamos até Spear e criaremos uma Área dois D que criaremos como nossa caixa de sucesso Então, vou clicar com o botão direito do mouse na lança adicionar o nó filho, Área dois D, e vou renomeá-la rapidamente para clicar na caixa dois D. Vamos clicar com o botão direito do mouse nela e anexar um script Agora, isso provavelmente será mais parecido com a raiz. Então, deixe-me ver. Acho que colocá-lo na pasta de armas faz sentido aqui e clicaremos em abrir. Então, criaremos o script em weaponlash Hit Box two D. Create dê a ele o nome de classe Hit box two D. Ok, então em nosso script HIT box, queremos nos conectar imediatamente ao sinal que a área já tem, que é a área que é Porque o que estamos tentando verificar é se entramos na área de uma caixa RT. Então, se fizermos a função underscore ready, então, em ready, podemos fazer a conexão de pontos na área inserida e vamos conectá-la a uma área inserida, que é uma função que estamos prestes a configurar Portanto, crie o sublinhado da função na área Inserida. Isso vai receber e a área dois D é o parâmetro. Então P área dois D e tipo de retorno v Ok, então uma área entrou nessa área, que tipo de áreas nos preocupamos? Nós nos preocupamos com caixas especificamente feridas. Então, se a área P é uma caixa de Hurt, dois D e o tipo ainda não existe, então deve ser uma era aqui. Então, por enquanto, poderíamos dizer algo como impressões, então, por enquanto, poderíamos dizer algo como Prance, que imprimirá uma mensagem no console Por que não tentamos assim? Porcentagens e aspas significam que vamos substituir isso por uma string Porcentagens de sucesso. Poderíamos até dizer, na posição, porcentagens, e então substituiremos essas sequências usando outro E temos três strings que precisamos substituir dentro dessa string Então, vamos passar uma matriz de valores que queremos fazer para a substituição. Então, a primeira será, digamos, eu. Então, vamos pegar a caixa Hit, que atingirá a caixa Hurt da área P. E então vamos dizer que a posição é a posição global do ponto da área P. Portanto, uma Área dois D ainda está no nó dois D, então ela ainda tem uma posição global. Isso funcionará apenas para perceber que nossa caixa de sucesso está, na verdade, atingindo a caixa de HRT Ok, agora precisamos fazer uma caixa RT no Oc. Então, vamos para o Oc e eu vou clicar com o botão direito aqui e criar um nó ágil Area two D. Vamos renomear isso para Hurt Box, e eu vou colocar B em maiúscula para caixa e eu vou colocar B em maiúscula para Dois D. Vamos clicar com o botão direito do mouse e anexar um script. Vamos querer machucar o Box 2 D. Isso pode aparecer em talvez personagens por enquanto. Na verdade, não teremos nenhum objeto destrutível, pelo menos nesta demonstração Então você pode argumentar: Ok, isso pertence mais à pasta de objetos, ou talvez você esteja organizando seus scripts em uma pasta de scripts que contém especificamente scripts A organização depende de você. É mais ou menos assim que estou fazendo as coisas. Então, os personagens cortam Hurt Box two D, vamos criá-lo lá Ok, agora esse script, precisamos chamá-lo nome de classe Hurt Box two D. Por enquanto, não vamos mudar mais nada sobre ele. Só queremos aquela etiqueta identificadora, Hurt Box two D. Agora, a caixa Hurt, você pode ver que ela também precisa de uma forma de colisão Então, vamos clicar com o botão direito do mouse e adicionar um nó secundário, forma de colisão E então, à direita, vou criar uma nova forma de círculo. Assim, podemos definir onde esse personagem pode ser atingido. Então, eu poderia pressionar W e movê-lo para cima. Podemos fazer com que seja meio grande aqui. Então, se eu torná-lo maior , mais ou menos assim, tudo bem. Você também pode preferir um formato de cápsula. Portanto, se selecionarmos o formato de cápsula você também poderá preferir um formato de cápsula aqui. Então, se fizermos uma forma de cápsula, que é mais parecida com um humanóide, podemos selecionar a forma de cápsula E então aqui, podemos simplesmente pressionar W, movê-lo para cá. Isso seria bom se você quisesse que todos os pixels exibidos na tela do k fossem, na verdade, áreas danificáveis Então você poderia apresentar esse argumento. E então nós só queremos que isso seja uma criança do Hurt Box Tot. E então nosso orc também precisa de uma forma de colisão. Então, onde os pés podem colidir para o c? Então, isso vai fazer mais sentido como uma forma de círculo aqui. E então olhamos para os pés dos orcs. Vamos reduzi-lo aqui, algo assim. Então, se escolhermos ter colisões entre nossos orcs e outros orcs ou orcs e o jogador, outros adereços e o objeto , essa é a forma que realmente usaríamos Agora, se você quiser que seus inimigos colidam com outros inimigos e jogadores e coisas assim quando eles se movem usando mover e deslizar, isso é algo que um personagem com corpo dois D pode fazer fora da caixa Mas terá um custo de desempenho associado a isso, já que na verdade está calculando movimento com base na física Se você quiser obter o número máximo de caracteres na tela, considere usar a tradução, assim como fizemos com a lança, o que significa que ela se moverá independentemente do que na tela na direção em que está tentando se mover Então, mantendo-o o mais idiota simples possível, depende de você o que você quer no final do dia E quantos milhares de inimigos você precisa na tela ao mesmo tempo. Ok, então antes de concluirmos isso, acho que a lança também precisa uma forma de colisão para a caixa de impacto Então, vou clicar com o botão direito aqui, adicionar um nó filho, forma de colisão dois D. Vamos para o canto superior direito Vamos fazer disso uma forma de círculo, e então vamos pegar a forma de círculo e movê-la até a ponta da lança e encolhê-la, algo assim Você pode preferir que seja em forma de cápsula. Depende de quão exigente você quer ser. Obviamente, a cápsula pode ser mais oval ou menos um círculo puro. Ou talvez até mesmo um retângulo. Então, se você quiser usar um retângulo, você pode fazer, digamos, a forma de um retângulo aqui em cima, encolher os lados assim, abaixar isso e talvez Portanto, use aqui a forma primitiva mais simples possível para a caixa de sucesso e, ao mesmo tempo, tente manter a forma real do sprite onde faz sentido Então eu acho que isso seria muito bom. Eu não acho que alguém realmente notaria que, você sabe, talvez essa metade da lança não tenha atingido aqui Se você realmente quisesse ser exigente, poderia fazer assim E sim, talvez isso fosse um pouco melhor. Apenas um pouco menos de chance de atingi-lo pode deslizar ao longo da borda aqui à esquerda. Mais uma vez, uma dessas opções, experimente e tenha uma ideia de como as coisas estão funcionando e veja se é adequado para o seu jogo ou não. Vamos começar o jogo agora e tentaremos fazer com que os orcs atinjam com esses projéteis Então, vamos ver que não é possível instanciar um nulo. Nível. OK. Então, neste momento, o projétil não está mais colocado na arma dois D. Isso é interessante. Vamos até o jogador, e eu vou pegar a arma dois D. Podemos ver que a definição da arma está definida aqui. Se eu expandir a arma dois D, vamos entrar na definição da arma. Então, temos o símbolo de busca. Talvez eu tenha movido a arma. Vamos ver. Onde está a lança Eu acidentalmente movi a lança da lança de armas para essa pasta diferente Então, vamos voltar para as armas. Ok, vai funcionar bem agora. Vamos clicar em Carregar. Ok, e então temos as lanças. Então, vamos para a saída. Vou diminuir um pouco, esses orcs estão realmente sendo atingidos pela lança, o que é bom Podemos ver a posição em que isso ocorreu. As informações da caixa de acerto não são muito úteis, mas pelo menos sabemos que tipo está atingindo qual tipo Se fosse um tipo de área completamente diferente , diria o nome da classe aqui. E isso está praticamente funcionando. 16. Causando dano aos inimigos com Hitboxes e Estatísticas: As caixas de acerto e as caixas feridas estão funcionando suficiente para que possamos perceber o impacto na caixa HRT, o que será o início de causar dano aos nossos inimigos orcs Então, neste vídeo, precisamos configurar as estatísticas do orc e ter certeza que estamos passando o dano atingido para o orc que sofrerá Uma grande parte deste tutorial será na verdade, definir as estatísticas da lança, as estatísticas do orc e configurar a interação entre as duas Então, se entrarmos no script do projétil, queremos que o projétil responda quando a caixa atingida atingir a caixa ferida, passando o dano do projétil para a caixa ferida e atingindo-a Então, vou colocar uma barra de exportação at para caixas de sucesso. Isso vai ser uma matriz de hit box two D. Ok. Agora, aqueles que eu quero atribuir na inspeção. Então, se eu clicar na matriz Spear dois D, a matriz de caixas de acerto está aqui Precisamos aumentar seu tamanho para um, clicar em um sinal no primeiro elemento e escolher a caixa de acerto. Então, agora temos uma referência à caixa de acerto do projétil dentro do script É feito como uma matriz porque algumas armas podem, na verdade, ter duas ou mais caixas de acerto. Então, fazemos disso uma opção desde o início. E o que vamos fazer é nos conectar a cada sinal da caixa de acerto ao cada sinal da caixa de acerto atingido para que nosso projétil possa causar o dano Então, vamos clicar com o botão direito do mouse na caixa de acerto dois símbolos D. aqui, símbolo do Lou, e isso passará para o script da caixa de acerto Então, em vez de imprimir o que clicamos, na verdade queremos emitir o que clicamos Então, vamos criar um sinal de alerta aqui. Sempre que a caixa de acerto reconhecer um acerto , passaremos pelo alvo que atingimos ou pela caixa ferida que atingimos nesse caso Então, vamos dizer que Hurt box aqui é um tipo de rt box two D. Ok. Então, em vez de imprimir aqui, vou recortar isso, e eu vou dizer aperte dot EMIT, e vamos passar isso com a área P como uma Hurt Box dois D. Então, agora, se passarmos para o script do projétil, podemos simplesmente nos conectar a esse sinal Então, vamos fazer isso antes de fazermos a parte de espera. Primeiro, diremos que assert hit booxes dot empty. Então, não queremos que isso seja verdade. Então, poderíamos dizer igual, igual a falso e dizer que precisa de pelo menos uma caixa de acerto para atingir um alvo Agora, isso depende um pouco de qual é sua intenção Teoricamente, você poderia ter um projétil que não precisa ser atingido Portanto, essa afirmação pode não ser necessária, mas para o nosso jogo, queremos que os projéteis sejam capazes de causar danos aos alvos inimigos Então, vamos deixar essa afirmação lá. Então, depois de nossas afirmações, podemos dizer quatro caixas e acertar caixas Vamos dizer box dot hit dot Connect, e poderíamos dizer em hit box hit. Então, vamos conectar esse sinal a uma nova função que estamos escrevendo aqui na parte inferior. Então, a função no Hit Box Hit vai usar uma caixa P Hurt pode fazer a caixa de sublinhado HRT se quisermos ser mais consistentes E isso vai ser do tipo Hurt Box two D e return void Ok, então com a caixa HRT, vamos chamar, digamos, P Hurt box Digamos que dobre o dano de DL e o valor será baseado em nossos cálculos aqui. Então, onde obtemos o dano para calcular? Bem, vamos declarar o dano final aqui. E vamos definir isso para dez por enquanto. E isso será um número inteiro. Portanto, todos os danos e HP do jogo serão baseados em números inteiros Só para simplificar, tecnicamente, você pode causar uma fração de uma unidade de dano, mas isso é muito confuso A maioria dos jogos usa apenas números inteiros. Ok, então diremos que lidamos com o dano final aqui e nos preocuparemos com o cálculo do dano posteriormente. Então, poderíamos dizer, para fazer o cálculo de danos. Ok, agora, em nossa caixa Hurt, queremos adicionar esse método de causar dano. Vamos até Hurt Box. Então, eu vou dizer que a função causa dano, e vamos transmitir o dano de um número inteiro Oh, poderíamos colocar um tipo de devolução aqui agora Vou devolvê-lo como nulo porque esperamos que o dano causado seja o dano que ele recebe estamos calculando no script do projétil Neste caso, estamos calculando no script do projétil em vez do script Hurt box Na verdade, vamos alterá-lo para um tipo de retorno booleano. Então, eu vou dizer que tente causar dano aqui. A razão para isso é que estabeleceremos a condição de que seja possível que as estatísticas sejam impossíveis de serem atingidas, então resolveremos isso aqui. Portanto, o ponto de falha final para saber se ele realmente sofrerá o dano será a invencibilidade nas estatísticas Então eu acho que isso faz mais sentido do ponto de vista da caixa. Então, diremos que, se não, um ponto do controlador de estatísticas pode ser atingido, então retornaremos false Agora, as estatísticas são onde estamos aplicando o dano. Ele gerenciará as estatísticas de tempo de execução do personagem. Então, precisaremos configurar tudo isso em um minuto. Então, agora provavelmente seria o momento certo para configurar isso. Então, aqui no topo, vamos querer usar o Export VR, uma referência de controlador de pilha Então, isso será do tipo controlador de pilha. Então, criaremos um novo script com. Vamos até a cena organizacional em duas visualizações em D, clicaremos com o botão direito do mouse nela e adicionaremos um nó secundário. Então, esse será um nó normal. Não é um espaço de posição. Este é um gerenciador de estatísticas, então tudo é banco de dados. Portanto, é um nó, não um nó TD. E vamos chamá-lo de Stat Controller. Tudo bem, clique aqui. Vamos anexar um script. Então, o nome dele será apenas Sat Controller, e vamos colocá-lo na pasta do personagem porque nosso personagem principal também terá um controlador de pilha. Vamos criar o script. Vou colocar o nome da classe e vou controlar o controlador vPasteDN Stat porque copiei isso Isso gerencia as estatísticas de tempo de execução de um objeto. Então, vamos ter coisas como VaraHP, que é um número inteiro, e podemos definir isso para um valor padrão Também temos o Var Max HP, que pode ser o mesmo. A ideia é que o HP nunca possa ser colocado acima do MX HP Então, se você quiser apenas cuidar disso agora, colocaremos outra ferramenta aqui no final, e eu direi valor definido. Portanto, o HP será igual aos homens do valor e do MaxHP Ok, então isso aqui apenas o limita para que você possa definir o HP acima do MaxHP Também podemos querer uma variável para é o objeto vivo. Então, diremos que, ao vivo, isso será um booleano. O padrão será verdadeiro. E então precisamos dessa função na qual estávamos recebendo um erro. Então, se eu marcar Hitbox, há a função can be hit Temos que implementar isso. Então, vamos ao Stat Controller. A função pode ser atingida, o que retornará um booleano Assim, podemos colocar as condições que quisermos aqui. Por enquanto, vamos dizer que voltaremos ao vivo. Então, se o personagem estiver vivo, ele pode ser atingido. Caso contrário, não poderá ser atingido. Então, aqui, se estiver vivo, poderá ser atingido, mas isso é inverter isso com o k. Então se não estiver vivo, retornamos falso Basicamente. Agora, aqui embaixo, diremos return true porque presumimos que, neste momento, ele causou danos porque as condições foram atendidas. Já aprovamos a cláusula da Guarda. Então, queremos pegar o controlador SAP, pegar seu HP e defini-lo com o novo valor. Talvez queiramos calcular isso logo acima. E como uma variável local. Portanto, o novo HP será igual ao ponto do controlador estatístico: HP menos é ponto do controlador estatístico: HP menos igual ao dano ou apenas menos, na Portanto, a tarefa está, na verdade aqui à esquerda do novo HP Então, configuramos o HP do controlador de estatísticas para o novo HP e retornaremos verdadeiro Também podemos querer colocar aqui um sinal que a caixa Rt emite, o que também seria um sinal de sucesso Ok, então eu quero testar tudo até agora. Vou definir um ponto de interrupção aqui à esquerda para que possamos acertá-lo no Debug se a arma conseguir danificar o personagem Então, vamos clicar em Play e ver se funciona neste momento. Tenho certeza de que estou perdendo algumas coisas. Então, podemos ver na parte inferior aqui que o dano causado não existe porque, na verdade, agora é dano triplo Então, mudamos o nome e , em seguida, vamos executar isso novamente. Atingimos o ponto de interrupção? Chegamos até aqui. controlador de pilha pode ser acionado, mas na verdade não atribuímos o controlador de pilha à caixa RT Portanto, esse pode ser outro caso em que queremos afirmar no topo que o controlador SAT realmente foi configurado Portanto, o controlador assert stat não é igual a null. O HRT Box precisa de uma referência do controlador para efetivar. Portanto, a caixa HRT precisa de uma referência ao controlador SAT para que possa alterar suas estatísticas. Então, vamos ver. Se formos para o TD View, modo local aqui em cima, e clicarmos na caixa RT, atribuiremos à direita o controlador de pilha aqui Caso esqueçamos, a qualquer momento, alguma caixa ferida, afirmamos que temos um substituto para nos pegar Então, vamos executar isso mais uma vez. Vamos acertar isso e você pode ver que voltamos à realidade. Você também pode ver na parte inferior que o novo HP foi configurado para 90. Nosso HP básico para o controlador de estatísticas é 100, então 100 menos dez, obtemos 90, então sabemos que está realmente sendo atualizado corretamente E a próxima coisa que faremos no início do próximo vídeo será configurar a máquina de estado orc para que possamos fazer a transição de vivo para morto quando o HP cair para zero e depois remover o orc da cena 17. Estado de morte quando o inimigo atinge 0 HP: Agora queremos criar uma máquina estatal para nossos inimigos. Vai ser incrivelmente simples. Haverá apenas dois estados logo de cara, que serão o estado de movimento ou o estado de morte, que o eliminará do jogo Então, vamos clicar com o botão direito do mouse em Oc para adicionar um nó filho. Eu vou dizer HSM aqui, e nós vamos pegar o Limbo Poderíamos renomear isso para Enemy HSM, e então eu vou clicar com o botão direito nele e anexar um script Então, isso vai direto para a pasta de inimigos slash EnemysHSM Vamos criar isso. Defina a parte superior aqui. HSM inimigo Essa é a máquina de estado dos inimigos dentro do Okay, então, olhando para o player HSM, vai ser muito parecido aqui Acho que, como na verdade mudamos para o Blackboard, esse script não precisa mais uma referência direta ao reprodutor de animação, que seria correto se eu examinasse aqui no plano do Blackboard Não há necessidade da segunda referência. Então, eu posso realmente cortar isso aí mesmo. Então, vamos copiar esse código do HSM do player para o script do HSM inimigo Então, digamos que, em vez de um jogador, esse será um script de NPC, que pode ter suas estatísticas definidas nele Então, um NPC do tipo NPC afirma que o NPC não é nulo. Portanto, o agente NPC deve estar configurado no HSM e nós o inicializaremos com o script Então, estou meio que mudando os nomes aqui, principalmente. Então, o script do NPC, vamos até a cena dos orcs no D View. E vamos querer clicar em OC, anexar um script. Diremos que isso é NPC e o colocaremos em personagens, não em Character Slash Enemy, ou pode ser em inimigos que dependem de você Criaremos esse script para o corpo do personagem. E vamos chamar isso de ClassName NPC. Portanto, o NPC terá apenas uma referência fácil ao controlador da pilha Para que não precisemos necessariamente referenciar essas duas coisas separadamente. Dentro da máquina de estado, é muito conveniente acessar as propriedades do agente porque você sempre sabe que o agente estará presente em qualquer script de máquina de estado depois inicializá-lo na máquina de estado Então, se exportarmos as estatísticas do VAR aqui e, em seguida, dizermos controlador de pilha, poderemos referenciar isso muito fácil dentro da máquina de estado Então, aqui à direita, atribuímos o controlador de pilha e, agora, dentro do HSM inimigo, os erros devem desaparecer desde que clicemos no HSM inimigo. Bem, isso não está certo. Deveria dizer NPC. Então, só precisamos reiniciar o projeto Cadle, ir para Projeto, recarregar o projeto Ok, e isso deve resolver isso. Agora atribuímos o orc, que é o NPC, e temos uma referência ao agente e às estatísticas, e isso deve ser a maior parte do que precisamos para nossa máquina de estado Ok, então vamos clicar com o botão direito do mouse no HSM inimigo. Vou adicionar um nó secundário. E vamos fazer um estado de limbo. Eu poderia renomear isso e dizer algo como NPC move state Bem, clique com o botão direito do mouse em anexar um script. Criar. Ok, então, a seguir, vamos criar um estado de perseguição para o inimigo. É aqui que estará a lógica central para nosso personagem se mover em direção ao jogador, além de reproduzir a animação de execução assim que a colocarmos no estado. Então, vou clicar com o botão direito do mouse no HSM inimigo. Vamos adicionar um nó secundário, um estado do Limbo. Vou renomeá-lo para Chase State. E eu vou clicar com o botão direito aqui, anexar um script. Então Chase afirma que provavelmente pertence a um inimigo. Vou clicar em Criar. OK. Vamos dar a ela um nome de classe no topo, Chase State, e vamos fazer um comentário. Então, isso vai acabar correndo em direção ao jogador onde quer que esteja no jogo. Por enquanto, vamos fazer que ele reproduza a animação. Vamos configurar uma transição do estado Chase para o estado de morte e garantir que nosso personagem, caindo para zero HP dê vida ao inimigo dentro do jogo Então, vamos dizer sublinhado da função, Enter. Quando entramos, queremos reproduzir a animação de execução. Então, podemos até mesmo fazer a configuração do sublinhado da função e, em seguida, obteremos aquele reprodutor de animação Até agora, sublinhe o player de animação do tipo player de animação, e vamos obtê-lo do Blackboard, assim como fizemos com o Portanto, o player de animação é igual a Blackboard dot get var. E estamos procurando o reprodutor de animação de citações finais e queremos reclamar se não o encontrarmos Então, temos o player de animação. Quando entramos no estado, reproduzimos a animação. Então, vamos dizer underscore animation player dot play, e queremos reproduzir a animação definimos aqui na parte superior Vamos fazer em Export var. Digamos que a animação do Chase. Claro. E esse será um nome de string. Vou defini-lo como padrão para ser executado. E depois copiamos isso para aqui. Então, reproduzimos a animação certa quando entramos no estado. Ok, e nosso HSM inimigo, nós já o inicializamos Nós já o ativamos. Então provavelmente vai funcionar. Então, podemos ver se funciona agora. Vamos entrar no modo de jogo. Oh, nós não colocamos o player de animação no Blackboard, é claro Então, isso nos diz imediatamente que houve um problema. Isso é bom. Clique em Enemy HSM, vá até o plano Blackboard e vamos fazer o Novo Plano Blackboard, gerenciá-lo e adicionar um player de animação variável Escolha o tipo de caminho do nó. Clique em OK. E agora, queremos atribuir um player animação ao player de animação do or e agora podemos usá-lo dentro de nossos estados. Ok, clique em Play novamente. E vamos ver se nossos orcs estão correndo. Todos eles são. Isso é ótimo. Então, precisamos do nosso estado de morte e precisamos configurar nossa transição. Então, vou clicar com o botão direito do mouse em Enemy HSM adicionar um nó secundário, que será Limbo State Renomeie isso para Death State. Clique com o botão direito, anexe um script e clique em Criar. Vamos chamá-lo de Estado da Morte no topo. Então, nome da classe Death State. Ok, agora em nosso estado de morte, também precisamos reproduzir uma animação muito semelhante à que fizemos no estado Chase. Esse é um código que vamos repetir aqui, mas como estamos fazendo apenas alguns estados para o nosso jogo, acho que fazer coisas como criar uma nova classe base é um pouco extra no momento. Então, eu vou copiar isso. Para o estado da morte. Bem, cole isso. E eu poderia simplesmente dizer que a animação aqui que queremos para o estado de morte é padronizada para morte, e fazemos com que a animação seja reproduzida da mesma maneira Mas então queremos reproduzir a animação aqui. E como não estamos usando um estado base, não precisamos nos preocupar com coisas como chamar Super para garantir que o código do estado da animação realmente seja executado, porque ambos usarão setup e Enter. Se você declarar uma nova configuração ou função Enter, ela realmente substituirá o que está na classe base se você esquecer de chamar Super e, a propósito, você chamaria Super Super significa apenas que, seja qual for a turma principal, você a executa neste momento. Então você pode ver que é um pouco complicado e confuso usar esse tipo de herança direta Se você tem cinco ou dez estados diferentes, todos em que são estados de animação porque todos são reproduzidos na animação exatamente da mesma maneira , vale a pena ter isso. Mas nós literalmente só teremos Chase e a morte, então é um exagero Mas Tay deve mencionar que essa também é outra maneira de fazer as coisas Então, no Inter, basicamente queremos tornar nosso personagem invencível Então, talvez queiramos fazer algo como agent dot stats dot LI, e queremos ter certeza de que isso seja definido como falso. Portanto, lembre-se de que quando um controlador de estatísticas não está ativo, então can be hit retornará false. Portanto, isso nos impedirá de atingir acidentalmente um personagem que está em estado de morte Eles também fazem algo como, digamos, função concluída, e declaramos essa função para que você possa chamá-la da animação ou de outros lugares E vamos dizer que o agente precisa de você de graça. Então, agente Qu está livre. Então, isso basicamente significa a rota Aosne the org. Vamos libertá-lo e tudo o que está dentro dele. Quando chamamos o método finalizado. Então, agora podemos ir para dois reprodutores de animação de visualização em D aqui na parte inferior. Vamos ver a animação da morte. Ampliamos a linha do tempo, vamos até o final aqui. Vamos adicionar Track, call method track no estado de morte. Em seguida, clicaremos com o botão direito do mouse aqui embaixo, inseriremos uma chave e procuraremos o método finalizado que acabamos de criar. Então, isso significa que, quando nossa animação de morte estiver concluída, ela chamará de finalizado ; o estado de morte liberará o agente assim que a o agente assim que renderização do quadro terminar e todo o resto for resolvido Então, normalmente você liga para um trimestre, não gratuito, para congelar gratuitamente imediatamente, e um trimestre espera outras operações sejam resolvidas adequadamente Então, isso realmente reduziria a quantidade de insetos estranhos que você pode pegar ao comer Ok, então a última coisa que precisamos fazer é entrar no HSM inimigo Vamos criar uma nova função para transições de configuração, que retornará nula Então, queremos adicionar uma transição do nosso estado de perseguição para o estado morte quando o evento de morte é emitido Então, quando você declara um evento aqui como este, esta é apenas uma string à qual nosso sistema responderá poderíamos ir até aqui e criar um evento de morte constante Será um nome de string igual ao de “ morte” em minúsculas, colaremos isso lá embaixo e poderemos nos conectar às estatísticas do nosso agente dessa forma Digamos que as estatísticas de pontos do NPC dot Alive mudaram. Não criamos esse sinal, mas vou pular aqui, então conecte-se. O sublinhado em NPC Alive mudou. Ok, então eu vou copiar isso para a parte inferior da função paste on NPC live changed, e isso vai ter o novo valor Então, vivo é um booleano. Poderíamos dizer P como parâmetro, se quisermos aqui. Eu geralmente gosto de fazer isso. E isso vai devolver um tipo de vazio Então, quando o NPC não estiver mais vivo, eu quero emitir o evento da morte Então, se P vivo é igual a falso, então vamos despachar o evento da morte OK. E quando adicionamos a transição, isso significa que essa transição acontecerá quando esse evento de morte ocorrer. Agora, ele ainda está nos dando uma mensagem de erro porque não temos o estado de Chase ou a referência do estado de morte aqui no topo. Então, podemos apenas dizer em export var Chase state, que é um estado limbo, e em export var death state, que é um estado limbo Agora salve o script no inspetor. Podemos atribuir o estado de Chase e atribuir o estado de morte. E agora, depois de chamarmos as transições de configuração, ele cuidará do gerenciamento dessas transições Acho que queremos chamar isso antes de inicializar, ou talvez logo depois Vamos fazer isso logo depois. Então, sublinhe as transições de configuração Nós chamamos isso. Configuramos nossas transições. Não deveria haver a necessidade de criar um estado de morte para perseguir porque não temos inimigos voltando à vida atualmente, mas você poderá adicionar esse tipo de coisa mais tarde. Certamente, esse seria um tema comum, especialmente para inimigos mortos-vivos Ok, então a última coisa para fazer isso funcionar muito rápido ir até a cena da lança e vamos pular na caixa de sucesso, ou é a lança? Certo, a lança. E queremos reduzir o dano final e defini-lo em 100, então será um golpe igual a um orc Clique em play e vamos ver se tudo isso se encaixa. Então, isso está nos dando um erro. Eu não criei um evento alterado ao vivo nas estatísticas do NPC Clique com o botão direito no símbolo do NPC, vá para o símbolo Lou. Clique com o botão direito no símbolo, símbolo Lou, clique com o botão direito em Stat Controller, símbolo Lou Ok, e aqui estão nossas estatísticas. Vamos criar o sinal, para que possamos dizer que o sinal ao vivo mudou. E isso passará o novo valor real como um booleano Voltaremos aqui e atribuiremos mais sinais, mas, por enquanto, quero ter certeza de que esse sinal seja emitido sempre que um valor real mudar Então, eu vou dizer valor definido. Então, primeiro, vamos evitar se o valor for igual ao valor que está sendo definido para ele. Portanto, se uma vida for igual, dois sinais iguais ao valor simplesmente retornarão. Caso contrário, uma vida ativa é igual ao valor. E, finalmente, um ponto alterado ao vivo é emitido com o novo valor Então, onde queremos calcular o Alive? Bem, um bom lugar para fazer isso seria neste configurador HP. Então, sempre que o HP muda, queremos verificar se o personagem ainda está vivo. Então, isso vai ser ao vivo, é igual a HP é maior que zero. Ok, então isso está resolvido. Agora temos o evento alterado ao vivo. Tudo isso deve ser acionado quando o personagem atingir zero HP. Vamos parar o jogo e executá-lo novamente e ver se o atingimos com uma arma. Assim, o personagem se remove sozinho? Vai para o estado de morte? E podemos ver que a resposta é sim. Então, leva 100 de dano. A HP chega a zero. Uma live é definida como falsa. O sinal é emitido. E então isso significa que, na máquina estadual inimiga, a transição é acionada porque esse sinal é atingido Esse patch no HSM inimigo emite o evento interno. Portanto, esses eventos da máquina de estado são separados dos sinais. Eles são apenas para a máquina de estado nos sinais de IA do Limbo no contexto maior de Gadot Então, temos esse evento interno de morte, e isso nos faz ir do estado de Chase para o estado de morte. Dentro do estado de morte, reproduzimos a animação morte em Enter, mas garantimos que isso seja definido como falso aqui. Em teoria, você não precisaria fazer isso, mas acho que não vai doer nada garantir que, se estivermos interpretando o estado da morte, que o personagem não esteja mais vivo, acho que está tudo bem. E então temos o método finalizado, que na verdade estamos apenas chamando da animação. Como você viu antes, a animação de morte aqui embaixo aparece logo no final de nossa animação, e é assim que fazemos nossos inimigos entrarem ao vivo assim que caem para zero de HP. Então, eu sei que há muitas peças se juntando. Eu recomendaria que, nesta parte, se você ainda não baixou os instantâneos individuais das partes , pegue aquele para este vídeo se estiver, você sabe, com problemas e veja onde talvez seu script esteja um pouco errado Então, o que estamos fazendo aqui com sinais é o padrão do observador É muito útil quando você quer que uma parte do código responda a uma alteração em outra parte do seu código. E algo como C Sharp, isso seria chamado de eventos e, em seguida, tratamento de eventos. Mas em Gadot isso é chamado de sinais. Essencialmente, eles são o mesmo conceito, no entanto. Portanto, é o padrão do observador Se você quiser pesquisar isso e ler mais sobre isso. Então isso vai ser um embrulho para isso 18. Rotação e direcionamento dos projéteis com carga de arma: Ok, então neste vídeo, vamos fazer com que nossa lança gire para a direção certa após a instanciação e que também possamos lançar a lança na direção correta Então, a forma como precisaremos configurar isso está dentro do nosso script D da arma 2 aqui. Então, em nosso jogo de sobrevivência, provavelmente queremos fazer com que um personagem possa ter várias armas ao mesmo tempo Portanto, na verdade, faz sentido ter algum tipo de gerente para todas essas armas. Assim, podemos criar um script de carregamento de armas que seja aparente para essa arma dois D, e podemos usar isso como um exemplo de forma de resolver coisas como a importação de nossas armas pelo jogador Então, vamos clicar com o botão direito do mouse no nó do jogador e adicionar um novo nó filho. Vou chamar esse nó dois de D, e então vamos renomeá-lo para carregamento de armas Vamos transformar imediatamente a arma dois D no carregamento da arma aqui, e eu deveria renomear a arma dois D para ficar como uma arma lança, deixando claro o que ela realmente E então vamos clicar em Weapons Loadout e adicionar um script. Então, esse será o carregamento de armas que pode ser usado no jogador, criado e, no topo, faremos o carregamento de armas com o nome da classe Então, esse será um script de gerenciamento para todas as armas que um jogador equipou. Então, aqui podemos pegar uma referência rápida à entrada do player. Ok, e agora podemos acessar o roteiro de armas de lança e insistiremos que, e insistiremos sempre que tivermos uma arma de lança, dependemos de que a mãe seja uma carga de armas que será consistente em todo o jogo Então eu acho que a configuração está boa. Então, vou fazer var underscore loadout aqui dentro do script D de nossas armas. E isso será do tipo carregamento de armas. Então, quando estiver pronto, vamos querer obter esse carregamento. Então, digamos que underscore loadout é igual a get parent, e devemos afirmar que o loadout não O pai de uma arma deve ser o carregamento da arma. Ok, e parece que eu poderia ter definido o nome da classe. São armas com S? Sim. Ok, então isso é o carregamento de armas aqui, não o carregamento de armas Ok, então temos uma referência ao script de carregamento principal. Isso cria uma dependência, mas também facilita o acesso às coisas de que precisamos Então, caso alguma vez tenhamos decidido que queríamos mudar esse padrão, criarei uma função aqui embaixo para Get direction. Então, a função Get direction retornará um vetor dois. E nesse caso, vamos usar o loadout para conseguir Portanto, retorne a entrada de pontos de carregamento de sublinhado. Direção do ponto. E é assim que resolvemos a direção, mas sempre podemos usar a função de direção G para lidar com isso. Então, se ligarmos, digamos, obtemos a direção em dez lugares diferentes, mas mudamos o carregamento Então, na verdade, não usamos mais um carregamento ou talvez o carregamento não use uma entrada, então só precisamos entrar aqui uma vez e mudar Então, talvez o carregamento tenha uma referência direta à direção, então simplesmente mudamos assim e ele funcionaria novamente Mas, na verdade, preciso mudar isso um pouco porque não vamos usar a direção. Vamos usar a direção voltada porque, lembre-se, direção é a entrada bruta. Pode ser um ponto vetorial zero, mas nunca lançaremos uma lança nos pés do personagem nesse estilo de jogo Então, na verdade, queremos ficar voltado para aqui, e vamos levar isso para Importar com frente para pontos. Então, vamos realmente resolver a direção para a qual o personagem está voltado e, em vez disso. Ok, então vamos pegar isso Get facing e, onde lançamos, vamos apenas lançar para ficar de frente para ficar de frente para frente. E se movermos nosso personagem, você já verá que podemos lançar na direção certa, e isso também deve incluir diagonais, assim Ok, então isso é metade do que precisamos fazer ali mesmo. Agora, também precisamos girar todos os projéteis que instalarmos. Então, vamos obter esse ângulo de rotação. Então, dentro do elenco, abaixo de onde criamos a cena do pacto para o projétil, vamos fazer o ângulo de rotação VR E vamos pegar o vetor voltado para ficar. Vamos converter isso em um ângulo aqui, e acho que está em brilho. Se eu clicar com o botão direito do mouse e fizer o símbolo Lou, podemos ver o retorno do ângulo vetorial em relação ao eixo X positivo em radianos Então, isso seria algo como Pi dividido por dois tipos de coisa. Ok, mas queremos girá-lo para que a lança ou outros projéteis estejam voltados para a direita, por padrão, como nosso Então, se o sprite estiver voltado para cima, queremos girar esse Pi dividido por dois ou cerca de 90 graus assim , então vamos adicionar Hi, que é uma constante dividida por dois, e isso fará com que fique voltado para a direita por padrão Sem dar conta, é realmente mais uma questão de tentativa e erro Mas vamos fazer essa rotação. Então, depois de instanciarmos o projétil e dizermos que é a posição global, vamos fazer a rotação do ponto do projétil e essa função leva radianos e essa função Então, temos nosso ângulo de rotação. Realmente, eu deveria renomear isso para ser anúncios rotativos. Então, vou coletar duas vezes esse Control R, e vamos dizer que gire os anúncios para ver a luminosidade, substitua tudo, e aí fica muito mais limpo Então salve e corra, e aí temos nossas lanças apontando na direção certa E isso também deve funcionar essencialmente com qualquer projétil Desde que esses projéteis estejam voltados para cima por padrão, caso contrário, você pode girar esse sprite individualmente na cena dos projéteis até que estejam voltados para a estejam Então, aí temos nossa mira e rotações para os projéteis e rotações para E para mostrar mais uma coisa, se eu soltar a direção , nossa direção agora é o vetor 20, mas ainda estamos atirando para a direita porque a face nunca será definida como vetor dois pontos zero. E é por isso que usamos face em vez da entrada de direção bruta. Ok, esse é um grande passo feito ali mesmo. 19. Adicionando efeitos sonoros e música: Vamos adicionar alguns efeitos sonoros ao nosso jogo. Primeiro, vou começar fazendo um efeito sonoro de lançamento e, então, talvez, quando os inimigos atingirem seu estado de morte, tenhamos a opção de fazê-los tocar um efeito sonoro lá também. Eu provavelmente ficaria longe dos sons de sucesso porque vários inimigos serão atingidos a cada segundo, e isso acabaria sendo, eu acho, muitos efeitos sonoros ao mesmo tempo. Você não gostaria de sobrecarregar demais seu jogador. Então, vamos começar com esses dois. Então, para a arma de lança do jogador, digamos que na arma em D, adicionaremos um reprodutor de som Então, em Export var audio player of type ou audio stream player two D. Queremos que sejam dois D porque esses projéteis existem dentro do mundo do jogo TD, então faz sentido afetar o áudio com base no posicionamento espacial da câmera e do projétil e tudo Então, pegaremos o reprodutor de áudio e teremos que colocá-lo aqui embaixo. Então, para adicionar o nó do reprodutor de áudio, vamos ampliar aqui e clicar com o botão direito do mouse na arma Spear, adicionar o nó filho Então, queremos que o stream player two D, adicione isso lá embaixo. E queremos atribuir um stream de áudio que possamos reproduzir aqui. Então, vamos descobrir os efeitos sonoros. Vou fechar todas as pastas. Vamos entrar no áudio. Vamos ver. O que eu estava usando? Acho que tivemos, tipo, efeitos sonoros de Ball Ok, deixe-me colocar meu fone de aqui para que não chegue pelo microfone Ok, então dentro de a, acho que estava com a barra 04, então poderíamos clicar duas vezes nela, ir para o canto superior direito e visualizar Sim, acho que era isso que eu estava usando no meu projeto de demonstração. Então, vamos pegar a barra e colocá-la no stream aqui Agora podemos simplesmente dizer a esse reprodutor de streaming de áudio para tocar sempre que lançarmos um projétil Então, vamos entrar em stream weapon. E quando tivermos o projétil lançado, diremos que, se o reprodutor de áudio não for nulo, solicitaremos que ele reproduza o clipe de áudio atual Então, aqui embaixo, depois instanciarmos o projétil, diremos que o reprodutor de áudio toca, e isso é basicamente tudo o que precisamos fazer A razão pela qual temos essa condição aqui é que, para algumas armas, você pode não querer que ela reproduza nenhum áudio, então vamos pular essa opção aqui Agora, uma coisa que quero ressaltar aqui é que estamos dando responsabilidades extras a esse roteiro de armas. Portanto, agora a arma dois D não é apenas responsável por instanciar os projéteis, mas também por mandar o reprodutor de áudio tocar quando o projétil for instanciado contratando sua própria referência ao carregamento das armas e criando um Então, algumas coisas estão acontecendo agora, não acho que isso seja avassalador e um problema para o jogo, mas é algo que você deve conhecer Se você perceber que seus scripts estão assumindo muita responsabilidade, considere dividi-los em vários nós com scripts diferentes e fazer com em vários nós com scripts diferentes e fazer com que funcionem juntos como peças individuais, em vez de um megascript gigante. Mas ainda não chegamos lá. O roteiro tem apenas 50 linhas. Na verdade, não é um problema. Se você tivesse talvez duas ou 300 linhas de código , provavelmente chegaria ao ponto em que precisaria de alguns subobjetos, eu acho Mas não se preocupe muito com isso. A maioria dos scripts deste curso é bem simples. Eu só quero que vocês saibam que, daqui para frente, um roteiro pode se tornar muito monolítico, e isso pode ser problemático a Temos uma arma de lança. Precisamos atribuir o reprodutor de áudio para que ele realmente reproduza áudio. Então, atribua e, em seguida, reprodutor de fluxo de áudio. Agora, se tocarmos, devemos obter nossos efeitos sonoros. Ok, sim, lá vamos nós. Toda vez que lançamos um projétil Ok, agora queremos reproduzir um efeito sonoro quando nossos orcs morrem. Então, vamos entrar na cena dos orcs. Tudo bem, clique no orc, adicione um novo player AudioStream Se quisermos, eu poderia renomear isso para ser um reprodutor de áudio de morte Poderíamos dizer. Ok, então agora gostaríamos de encontrar um efeito sonoro de morte adequado. Brincando um pouco com isso, acho que o inimigo Death 01 é demais. Até mesmo flash oh two também é um pouco demais. O fato é que haverá inimigos caindo como moscas nesse tipo de jogo Então, precisamos de algo muito sutil ou talvez até mesmo nenhum. Acho que estou procurando algo mais parecido com o Step grass 03. Agora, isso pode parecer um pouco estranho, mas acho que qualquer coisa que seja mais longa do que isso vai ser demais para ver no que vai dar, pode até mesmo remover isso completamente Então, vamos atribuir o Step grass oh three ao stream aqui e, para pedir que ele reproduza esse efeito sonoro na morte, vamos até o reprodutor de animação. No canto inferior esquerdo, selecionaremos a animação da morte. E adicionaremos uma nova faixa, adicionaremos uma faixa aqui, chamaremos o método no reprodutor de áudio Death, clicaremos com o botão direito do mouse no início da animação, inseriremos a tecla e queremos jogar. Então, é como se estivéssemos escrevendo um script ao definir esses quadros-chave de animação, exceto que temos a linha do tempo, então podemos dizer exatamente quando queremos que ela reproduza essa animação, e é muito fácil movê-la para um momento diferente apenas arrastando-a para um Assim, você poderia criar um script de tudo isso escrevendo o código de script GD se quisesse e simplesmente pular o player de animação Mas, obviamente, o reprodutor de animação meio que torna muito mais fácil fazer isso visualmente. Ok, então agora, se tocarmos, devemos tocar os dois efeitos sonoros. Então você pode ouvir quando os orcs mergulham, eles tocam aquele pequeno efeito sonoro Está um pouco quieto, mas talvez esteja tudo bem. Se acharmos que as lanças estão muito altas em comparação, podemos até pegar o reprodutor de streaming de áudio da lança e diminuir um pouco o decibel do volume aqui E aperte play e execute mais uma vez. Você pode até mesmo editar isso enquanto o jogo está rodando. Então, poderíamos simplesmente deixar isso lá embaixo. Ok. Você pode ver que já está muito mais silencioso. Mar, uma das coisas boas do cado é que você não precisa necessariamente fechar o jogo para mudar suas propriedades. E vamos atacar um inimigo. Ok. E a diferença de volume entre eles é um pouco menos pronunciada. Então, provavelmente está bom agora. Como um pequeno bônus para este vídeo, se você quiser adicionar música, vamos ao mundo e vamos adicionar um reprodutor de fluxo de áudio, um reprodutor fluxo de áudio de dois D, apenas a nota padrão Então, transmita o player aqui e escolha este, o Audiostream player Ok, então com nosso reprodutor AudioStream, vá para a direita e vamos querer que isso seja reproduzido automaticamente E acho que para fazer um loop, primeiro precisamos carregá-lo dos três MP de áudio. Então, vamos fechar tudo no canto inferior esquerdo novamente, ir para Áudio e temos a música de box jump do pacote The Red Hearts. Então, vamos trazer isso para o canto superior direito. Na verdade, não é P três. É um OGG de pontos, mas os dois formatos de música são suportados no KDO, então funcionará bem E então queremos pegar isso e marcar Loop on. Mas talvez precisemos fazer isso no canto inferior esquerdo. Então, clique duas vezes no OGG aqui. Ok, e então verifique o loop aqui. E quando chegar ao fim, deve repetir a coisa toda. Ok, então isso é bom. Ok, então a última coisa antes de jogarmos o jogo, vou pegar o volume DB e colocá-lo em menos 20 , porque acho que provavelmente vai ficar bem alto, caso contrário. Então, vamos clicar em Play e ver no que vai dar. Ok. Assim, podemos ouvir a música, e ela ainda está bem alta. Então, vou levar isso para menos 30. Talvez até menos 40. Sim, isso provavelmente é um pouco mais apropriado. Então, agora temos o áudio. Temos a música e temos um efeito sonoro de Enemy Death. Então, esse é o básico para efeitos sonoros de áudio e música dentro do jogo, e podemos continuar a partir daí 20. Sistema de combate Singleton: Ok, então o tipo básico de dano e combate por projéteis funciona no momento, mas não sabemos realmente quanto dano está sendo causado aos inimigos no contexto do jogo Então, uma maneira de fazer isso que também melhoraria visualmente a jogabilidade seria o texto de combate flutuante. Então, sempre que um desses personagens sofre dano na caixa de ferimentos, podemos nos comunicar, digamos, com um sistema de combate, por exemplo, flutuando um texto de combate na posição em que sofreram dano toda vez que sofrem dano. Então, isso significa que haverá muitos números flutuando pela tela, mas acho que isso funciona muito bem para o estilo de jogo. É muito baseado em ação e queremos feedback imediato sempre que estivermos causando dano a inimigos E também queremos ver os benefícios de aumentar o nível de nossas habilidades, assim como nosso personagem ficar mais forte Para criar nosso sistema, vamos querer fazer isso como um objeto Singleton, que significa que há uma referência a essa classe ou sistema em todo o jogo E se o definirmos como carregamento automático, ele sempre estará lá em segundo plano e poderá ser facilmente referenciado pelo nome Você também pode implementar padrão Singleton no próprio script, mas faremos isso do jeito Gada, que é um pouco mais simples e fácil Então, aqui no topo, vou criar uma nova cena. Vamos criá-lo como outro nó, e esse será um nó base. Se vocês são dois aqui, você pode renomeá-lo para sistema de combate Em seguida, clique com o botão direito do mouse, anexe um script, sistema de combate. Podemos salvar isso na raiz ou criar uma pasta de sistemas para salvá-la, que provavelmente seria minha preferência, e eu a criarei lá. Agora, queremos salvar esse sistema de combate na pasta de sistemas. Então, o sistema de combate dot TSC, salve isso. E agora vamos fazer um carregamento automático para que esse script de nó possa ser referenciado em nosso jogo apenas usando o nome Então, vou para as configurações do projeto. Então temos Globals aqui. E queremos adicionar um novo TSCN como global. Então clique aqui, vá para Sistemas e depois faça TSCN. Você também pode ver que pode selecionar um script GD de pontos como sistema de combate, e o que isso faria seria criar uma nova instância do script de nó em seu jogo assim que o jogo fosse lançado Mas se você usar o ponto TSCN, terá a vantagem de poder usar variáveis de exportação porque essa é uma cópia muito específica do sistema de combate Se eu clicar duas vezes aqui e adicionar isso como nome do nó do sistema de combate , agora temos esse sistema de combate como um Singleton global e um lado do nosso jogo E a diferença entre carregar automaticamente um script GD de pontos e carregar automaticamente o SEN diretamente é que, se fizermos algo como Exportar var spawn count, número inteiro igual a dez , podemos definir isso aqui Mas se você instanciar um script que ainda não tenha sido definido como uma cena ou um nó , você não teria a capacidade de realmente personalizar propriedades como essa com antecedência. Agora, tenho certeza de que existem maneiras de contornar isso, mas essa é uma vantagem de usar o dot TSE Ok, então temos nosso sistema de combate. Vamos querer algum tipo de função de relatório de danos. Então, vou meio que redigir isso. Aqui. Digamos que função. Digamos que o relatório tenha sido atingido. Eu acho que isso faz sentido. Digamos que temos um alvo que foi atingido e podemos dizer que dois D não poderiam ser qualquer coisa no jogo que pudesse ser atingida. Geralmente, isso seria como um corpo de personagem ou um corpo estático. Mas usaremos apenas a classe base para maior flexibilidade. E então temos aqui a quantidade de dano. Portanto, o dano P é um número inteiro. Isso retornará vazio. E então, neste sistema de combate, criaremos nossa cena para o texto de combate flutuante. Então, vamos até o topo e podemos dizer em Export var, cena de texto de combate flutuante. E essa será uma cena repleta de tipos. E aqui no Report Hit , por enquanto, vamos dar uma olhada. Ou, se quiser, você pode até mesmo cometer um erro push e dizer não implementado. Isso lhe daria um pouco mais de feedback se você se esquecesse de implementar um script, em vez de apenas executar a função e passar para que não houvesse nenhum erro, mas também não fizesse nada. Então eu acho que isso é um pouco melhor durante o desenvolvimento, na verdade. Agora vamos passar para o nosso script HRT Box two D. Então, Control P, HRT Box two D. E aqui dentro, podemos referenciar o sistema de combate Ok, então o relatório de pontos do sistema de combate chegou, e queremos o objeto que o controlador estatístico está gerenciando Então, eu não acho que o controlador de estatísticas realmente tenha uma referência a isso ainda Se dermos uma olhada rápida na cena dos orcs, vamos clicar no Stat Podemos ver que não há nada aqui no lado direito para obter uma referência ao Oc. Poderíamos simplesmente fazer isso como um tipo de referência get parent ou podemos torná-lo uma variável de exportação. Se você quiser ter certeza de que a conexão é mais absoluta , eu escolheria at export. Porque isso significaria que se, por algum motivo, você movesse o controlador de estatísticas um nível abaixo, como se fosse pai para outra coisa , Get parent não retornaria mais o orc Então, se usarmos at export, podemos garantir que ele retorne o c. Poderíamos dizer algo como corpo ou personagem, talvez até objeto, mantendo-o mais genérico. E então esse pode ser apenas o objeto para o qual esse controlador está gerenciando estatísticas, e eu vou atribuí-lo no canto superior direito ao orc aqui Agora, se voltarmos para a caixa Hurt, podemos usar o objeto ponto do controlador de estatísticas aqui, e então podemos transmitir o dano P de dano Ok, então isso dará ao sistema de combate tudo o que precisamos saber sobre onde posicionar o texto e quanto dano atribuir ao texto. 21. Animando texto de combate flutuante: Agora precisamos do texto de combate flutuante em si. Então, vamos criar uma nova cena aqui. Clique em mais e faça a interface do usuário. E vamos fazer com que o nó base seja como um texto de combate flutuante. Mas o texto real será atribuído como rótulo secundário. E isso nos ajudará quando estivermos usando o reprodutor de animação para animar, porque não queremos mudar a posição da raiz Queremos apenas alterar a posição do texto em relação à raiz do controle de texto flutuante do Combat. Então, clique com o botão direito aqui, adicione um nó filho, procure o rótulo. E então vamos clicar com o botão direito do mouse no animação Adhild de texto flutuante de combate Ok, acho que é disso que precisamos aqui, então vamos controlar S. E podemos salvar isso. Talvez criemos uma pasta para a interface do usuário. Esse é o tipo de interface do usuário ainda. Então, vamos criar uma nova pasta. Vou digitar na interface do usuário. OK. E então, o texto de combate flutuante pontua TSC e pode ir direto para lá Então, fique seguro. OK. E agora precisamos de um script anexado à nossa raiz aqui. Vou clicar com o botão direito do mouse no texto flutuante de combate, anexar um script e criá-lo na pasta da interface do usuário, ponto de texto de combate flutuante gD. Vamos querer uma referência ao rótulo para que possamos manipulá-lo aqui Portanto, controle var label label. Então, vamos atribuir o rótulo aqui. E queremos criar algum tipo de função inicializada. Se você já usou o Gado, provavelmente sabe que há uma função de sublinhado e malha Essa função é usada quando um nó está sendo criado na cena. Mas, nesse caso, precisamos esperar até que o objeto já tenha sido criado. É por isso que precisamos criar. Então, se você já usa o Gadot há algum tempo, talvez saiba que há uma função de sublinhado e uma função de TI Portanto, essa é uma função substituível em que ela pode executar o código antes que todas as propriedades tenham sido definidas para seu sistema Você pode usá-lo para passar parâmetros opcionais para definir essas propriedades ao criar um nó a partir de uma chamada de função em vez de existir dentro de uma cena compactada, como aqui, que é o que você costuma fazer. Basta configurar a cena e, em seguida, instanciar a cena a partir de uma cena ritmada Então, na verdade, não é isso que queremos fazer. Não estamos tentando personalizar a função inicializada. Estamos tentando fazer com que o texto de combate flutuante seja executado quando já estiver em cena. Então, eu só queria fazer essa distinção lá. Ok, então o que queremos fazer no script de texto de combate flutuante é ter a opção de definir o texto no rótulo, e faremos isso diretamente com uma espécie de função delegada aqui com texto de conjunto de funções Então, colocaremos o texto no rótulo, mas o faremos operando por meio do texto de combate flutuante do nó raiz. Então, defina o texto e diremos o texto P, que é uma string, retornaremos void e pegaremos o texto com pontos do rótulo e definiremos como igual ao texto P. Então, uma razão para fazer isso é que nosso OK, então, é claro, vamos querer definir isso sempre que instanciarmos a cena de texto de combate flutuante. Portanto, você pode fornecer um nome de classe aqui para que possamos obter facilmente esse método de texto definido. Então, nome da classe, texto de combate flutuante, clicaremos em Controles lá. E agora, em nosso sistema de combate, sempre que denunciamos um golpe, queremos exemplificar nossa cena de texto de combate flutuante. Veja, digamos que o texto Vara seja do tipo texto de combate flutuante. E obtemos isso instanciando a cena de texto de combate flutuante Então, entre e depois instancie. OK. E então queremos acrescentar isso quando criança. E agora não queremos realmente adicionar o texto como filho do alvo P, porque quando o alvo P é excluído da cena, como acontece com a animação da morte, ele também remove seus nós secundários como o texto flutuante de combate. Então, como temos esse sistema global, o sistema de combate para lidar com o texto, acho que talvez possamos nos safar de simplesmente adicionar filho no próprio sistema e, em seguida, adicionar o nó de texto. Agora precisamos definir a posição global para a posição do alvo P. Portanto, a posição global do texto é igual à posição global do ponto-alvo E se essa parte não funcionar ou tivermos outros problemas, podemos obter uma referência a , tipo, uma camada de tela, interface real e a posição nela sob algum tipo de pai semelhante ao que estávamos fazendo com um projétil, então só precisamos de um pai para segurar todo o texto Mas a posição deve ser onde o inimigo sofreu danos, é a ideia aqui. Agora, queremos pegar o texto e definir seu texto. Portanto, defina o texto como uma sequência de P de dano. Portanto, o dano P é um número inteiro. Nós o convertemos em uma string dizendo STR e, em seguida, colocando o dano P entre parênteses E então definimos o texto com esse valor de string. Então, se definirmos a cena de texto flutuante do sistema de combate aqui, agora estou vendo a cena Singleton, o sistema de combate, podemos ir até aqui e carregar rapidamente nosso texto de combate flutuante Então, temos essa referência à cena lotada aqui à direita, então deve ser instanciada vamos clicar em Play e tentar Ok, então vamos fazer com que o dano seja atingido. Ok, sim, isso é mais ou menos o que esperamos. E veja, muito importante quando a orcha é removida da cena, o texto não se remove sozinho Ok, agora vamos lidar com a animação do texto de combate flutuante. Então fizemos isso no player de animação. Crie uma nova animação na parte inferior. Novo. E vamos ver. Podemos chamá-lo do que quisermos. Vou usar float up e, em seguida, precisamos adicionar algumas propriedades para animar Portanto, adicione a etiqueta da faixa de propriedade da faixa, especificamente a etiqueta, porque queremos essa posição de deslocamento Então, vamos procurar uma posição aqui. OK. Agora, não podemos ver nada porque não há texto padrão no rótulo, então vou clicar no rótulo e dizer DEF como padrão aqui Talvez também queiramos atribuir um tema com uma nova fonte padrão que se adapte um pouco melhor ao nosso jogo da Pixar Então, podemos fazer isso clicando no texto flutuante de combate. Indo para o tema no lado direito. Faça um novo tema, expanda isso, selecione uma fonte padrão e eu escolherei o que já instalamos no início do projeto cinco x sete, que você pode ver que é uma boa fonte Pixar Então, se quisermos reutilizar esse tema, o que provavelmente fazemos Vou clicar com o botão direito do mouse e salvar isso no projeto, e a interface do usuário soa bem. Então, vamos apenas dizer tema do jogo. Dot TRS por enquanto. Ok, se fecharmos isso, você pode ver que agora é referenciado pelo nome do arquivo Ok, agora, algumas coisas. No nó raiz, o texto de combate flutuante, podemos ver que basicamente tem essa caixa gigante. Na verdade, não precisamos que seja tão grande. Então vá para o layout. E então, em vez de Anchors preset full rect, vamos mudar isso Então, agora o controle é apenas um pequeno ponto aqui em cima, e a etiqueta tem seu próprio tamanho quando criança. Depois, outra coisa sobre o texto de combate flutuante. Eu quero pegar o mouse e mudar o filtro para ignorar, apenas para que os cliques do mouse ainda apareçam na tela Mesmo que eles estejam tocando nesse texto flutuante de combate, quero que os cliques do mouse Portanto, se houver alguma interface de usuário na tela, isso não interferirá no pressionamento do botão da interface do usuário. Isso é muito importante. E agora voltamos ao nosso reprodutor de animação e vamos definir a posição Então, vou ampliar na parte inferior. Vamos clicar com o botão direito do mouse no quadro-chave da posição e movê-la para onde quisermos que a posição inicial esteja Então, o 00 é onde nosso inimigo sofreu danos. Acho que só quero ter certeza que começa em algum lugar acima disso. Então, eu vou para w para mover o texto. Vou movê-lo para cá e, em seguida, definiremos a posição aqui Então, vá para o layout no lado direito e, em seguida, vá para transformar e quadro-chave da posição Então eu tenho menos 15 pixels no Y. E então podemos ver quanto tempo queremos que isso dure Talvez meio segundo. Você também pode ativar o snapping, se isso ajudar Ok, então 0,5 segundos. E então vamos movê-lo para cá. Então, mais ou menos assim , enquadre-o novamente no lado direito, usando apenas o botão do quadro-chave Ok, e agora ele vai ser animado entre esses dois pontos Então, se eu for para o início e jogar, você pode ver que ele vai animar esse movimento de posição Também podemos alterar a duração total para 0,5 segundos. E então, se quisermos, podemos resolver isso no final fazendo add track track call method track na raiz flutuante do texto de combate. E então clique com o botão direito aqui, insira e digite quarre Ok, isso garantirá que o texto se limpe depois concluído nessa cena, sem precisar personalizar o script de mais nada, na verdade Podemos simplesmente chamá-lo a partir da animação. Agora, isso provavelmente funcionaria, certo, agora, mas é muito básico. Vamos testá-lo. Apenas certifique-se de que funcione. Ok, sim, eu não toquei a animação. Então é porque eu não configurei a reprodução automática aqui. Então, no canto inferior direito do player de animação , reprodução automática ao carregar Ok, agora clicamos em Play novamente e estamos recebendo nossa animação. Ok, então isso funciona em um nível muito básico. Não é nada ruim. Mas enquanto estamos aqui, por que não torná-lo mais interessante? Assim, posso adicionar uma faixa na faixa de propriedades do rótulo e vamos fazer, digamos, a escala. Ok, então isso nos permitirá torná-lo maior ou menor com o passar do tempo. Então, vamos estruturá-lo como está no horário 00. Digamos que cerca de 0,15 segundos ou acho que estou caindo para 0,16 67 Isso realmente não importa aqui. você pode alterar seu encaixe na parte inferior direita, propósito, você pode alterar seu encaixe na parte inferior direita, se quiser ter um encaixe de quadro-chave mais personalizável Então, vamos rotular e depois transformar a escala. Vamos medir seu tamanho e aumentá-lo. Então, talvez 1,5 ou talvez até dois. Podemos começar com isso e reduzi-lo, se necessário. Então, vou estruturar isso. Então, agora ele vai passar do tamanho 1,0 para 2,0. E então, quando estiver desaparecendo, queremos que fique bem pequeno Então, vamos levá-lo para, digamos, o tamanho 0,1 e, em seguida, quadros-chave. OK. Agora, se reproduzirmos nossa animação, é mais ou menos assim. Talvez a escala seja um pouco grande demais neste segundo quadro-chave, então vou levá-la para, digamos, 1,5 Eu acho que está certo. Clique em play. Ok, isso funciona muito bem. E também podemos pegar a posição e deslocá-la talvez para a direita quando ela estiver atingindo esse ponto de tamanho máximo Então, vamos pegar a posição aqui com o modo de movimento W e movê-la para a direita ou algo assim e, em seguida, enquadrá-la. Ok, e agora vamos jogar novamente. Agora podemos ver como o texto aparece para a direita e depois volta para o canto superior esquerdo Outra coisa que poderíamos fazer seria mudar a cor do Alfa ao longo do tempo. Então, vamos adicionar uma faixa na faixa de propriedades do rótulo e fazer com que ela se automodule. Portanto, isso afeta apenas esse rótulo, não quaisquer nós secundários. Então, vou me automodular na etiqueta. Vamos clicar com o botão direito do mouse para inserir uma chave no início. Portanto, este será nosso branco padrão com Alpha completo. Vamos para 0,15 ou onde quer que nossos quadros-chave estejam encaixados aqui e insira uma 0,0 1667 para mim. E então vamos mudar a cor para vermelho ou algo assim, porque isso é para danificar o texto. E então vamos até o final aqui. Clique com o botão direito do mouse para inserir uma chave e a alteraremos para, digamos, zero Alpha. Pode jogar. Então agora é mais ou menos assim. Acho que faria mais sentido trocarmos o primeiro quadro-chave por este Então, vou arrastar isso na linha do tempo. Vou puxar a esquerda aqui até o ponto 0,0 1667. Isso passa por aqui. Então, agora vai começar em vermelho e ir para branco. E poderíamos terminar com uma cor branca também. Então, vou clicar aqui, ir até o valor e alterá-lo para 255 para o verde e o azul Então, termina em branco, embora totalmente transparente. Se eu jogar algumas vezes aqui, parece muito gradiente. Quero dizer, na verdade é porque estamos apenas passando de uma cor para outra cor durante um período de tempo Então, o gradiente seria assim da esquerda para a direita. exemplo, ele vai do vermelho para o branco à medida que avança pela tela, exceto que, em vez disso, estamos fazendo isso com o tempo Então, depende de você como você gosta daqui. Você pode simplesmente mudar isso para vermelho também. Então, é vermelho o tempo todo. A única coisa que muda é a transparência. Então você também teria que definir o terceiro ponto do quadro-chave , mais ou menos assim. Em vez disso, talvez queiramos que fique mais escuro com o tempo, para que pudéssemos pegar os valores aqui e torná-lo como um vermelho escuro , mais ou menos assim, e ver como funciona Sim, isso parece muito bom, eu acho. Talvez o vermelho seja um pouco vibrante demais, então eu poderia pegar o inicial e torná-lo mais ou menos assim. E talvez possa ser um pouco mais brilhante no pico. Vamos tentar, ok, do escuro para o claro e depois para o escuro novamente. Então, isso parece funcionar muito bem. Eu meio que gosto disso. Isso é puramente uma questão artística de preferências pessoais. Então, realmente, o que você quiser, vá com isso. Ok, então vamos jogar e testar, e teremos nosso texto de dano assim que atingirmos os inimigos. E me parece que se move muito rápido. Então, talvez precisemos dobrar a duração dessa animação. Então, se clicarmos no reprodutor de animação, podemos simplesmente mover esses quadros-chave, e essa é uma das grandes vantagens de usar um editor de animação de quadros-chave em vez de, você sabe, codificá-lo É mais fácil iterar e fazer pequenas alterações para ajustá-lo para que esteja onde você deseja Então, vamos usar esses quadros-chave para o Kframe. Coloque isso no final aqui em 1.0. Isso também deve ir para 1.0. E você pode arrastar uma caixa sobre vários quadros-chave e movê-los todos de uma vez desse jeito Então eu posso arrastar uma caixa aqui, e movê-la para, poderíamos tentar 0,5 segundos, qualquer coisa. OK. Agora, isso é muito lento lá. Então, talvez queiramos que isso seja mais parecido com o carregamento frontal. Vamos trazer isso para lá. Clique em play. OK. Quer dizer, não tenho certeza. Teremos que tentar e ver como realmente fica na tela. Parece que demora um pouco demais para desaparecer. Então, talvez isso pertença mais esse lugar. Um pouco mais adiante. E talvez 1,0 segundo seja muito tempo. Vou meio que arrastá-lo até lá. Então, qualquer que seja o ponto do quadro-chave de 0,8 segundos, essa será a duração do clipe Talvez o texto também seja muito pequeno. Então, acho que uma maneira de termos uma ideia é colocar uma cópia no cenário mundial para que possamos vê-lo aqui como está. Ok, então aqui está a mensagem do nosso pai. Acho que podemos realmente escrever, clique aqui e criar filhos editáveis, e então podemos clicar no reprodutor de animação e testá-lo e ver aqui Se mudarmos para flutuar, isso funciona? Sim, meio que sim. OK. Sim, isso ajuda muito. Então você pode ver realmente como vai ficar na jogabilidade real, porque temos a cena simulada aqui Ok, então talvez vamos assumir a posição aqui, e eu vou mudar isso um pouco para baixo. E parece que também podemos criar um quadro-chave aqui, então isso é bom Então, isso realmente resulta em 28 menos 31? Vamos fazer com que desapareça um pouco mais rápido. Então, eu nunca tentei dessa forma, especificamente. Parece que você pode usar o quadro-chave no rótulo, mas não pode ajustar o reprodutor de animação diretamente ao editar a partir dessa outra cena Portanto, há uma pequena desvantagem aqui. Eu poderia mudar a automodulação no primeiro quadro. E faça o keyframe lá. Ok, então isso funciona. Isso atualiza o player de animação. E então eu posso entrar na cena de texto de combate flutuante. E eu quero pegar a cor modular e movê-la muito mais para a esquerda Então, ele ficará vermelho mais rápido, mas eu realmente não gostei quando estava vermelho o tempo todo. Ok, e então eu vou aqui e adicionarei outro quadro-chave. E nisso, farei com que seja totalmente transparente. Portanto, ficará visível na tela por mais tempo. Ele não desaparecerá até o final da animação completa Vamos jogar e vou tentar isso mais uma vez. Talvez aqui eu também queira que sua cor seja branca. Então eu vou fazer isso. Então, basta ter um flash de vermelho. Uma última coisa no canto inferior direito se você usar o modo de interpolação aqui, poderá alterá-lo para E vou fazer isso para a posição, a escala e as propriedades de automodulação Então, se você olhar bem de perto aqui, ele coloca uma pequena curva nos lados esquerdo e direito para isso. Então, se isso estiver funcionando como outros editores de cronograma, que eu acho que funciona, isso significará que será uma curva de entrada e saída, em vez uma transição linear para a animação Então, vamos testar isso aqui e ver se esse é o caso. Isso é o que eu esperaria de outras coisas, como o editor de vídeo DaventIrsolt E parece que há essa flexibilização aqui. Então, vou trocá-lo de volta bem rápido, só para comparar. Nós levamos isso para linear. Sim, agora a velocidade é apenas consistente. Então, eu estava escrevendo minha suposição. Então, isso pode nos dar um pouco mais de força à animação, porque ela tem seus momentos lentos e seus movimentos rápidos Se clicarmos em play, testaremos isso mais uma vez aqui, e acho que funciona bem por enquanto. Então eu vou clicar em play. Vamos testá-lo. Acho que a animação é um pouco longa aqui. Só precisa ter aquele momento em que possamos lê-lo claramente Ok, então, mais uma vez, vou encurtar um pouco a animação aqui Puxando todos os quadros-chave para 0,7 aqui. A animação termina em 0,7. Vamos jogar mais uma vez e testar. Acho que vou terminar depois disso. Ok, então o desbotamento agora é muito rápido. Ok, e então para a posição em que está desaparecendo, eu quero movê-la também Então deixe-me arrastar isso até aqui para que eu possa ver. Clique no rótulo, talvez a carne de porco esteja lá. Farei o quadro-chave da posição e, em seguida, arrastarei esse ponto de volta para a direita Acho que isso só tornará a animação um pouco mais sutil. OK. Sim, então agora, quando está desaparecendo, não se move tão longe E eu acho que é um pouco mais suave de se ver. Então, poderíamos continuar assim por muito tempo. Acho que você entendeu. Basta personalizar a animação de acordo com que você achar que faria ela se sentisse bem em termos de cor, escala, transparência, posicionamento, etc As principais coisas deste tutorial, porém, em termos de código, são apenas garantir que você tenha o sistema de combate. É carregamento automático. Você diz para ele relatar o dano e, nesse relatório, você coloca o texto de combate e o adiciona não como filho do nó alvo que sofreu o dano, mas como um nó do sistema ou apenas um nó persistente que nunca se removerá sozinho. E você remove o texto de combate flutuante em sua animação chamando Q de free. E essa é basicamente a essência todo o resto é mais detalhe artístico 22. Movimento do inimigo (P21) com rastreamento de jogadores no Godot 4: Os projéteis já têm a capacidade de danificar e matar um inimigo, mas nossos inimigos na verdade não caminham em direção ao jogador Então, para que os orcs se movam em direção ao jogador, primeiro eles precisam de uma referência ao jogador Seria um pouco complicado ter uma referência direta entre o orc e o jogador inicialmente, porque eles não existem na mesma cena quando o jogo começa Quando geramos inimigos no mundo do jogo, eles vêm de uma cena lotada Então, eles não existem aqui até serem realmente colocados em cena pelo sistema de desova. Então, o que poderíamos fazer em vez disso é ter um recurso de referência, podemos chamá-lo de contexto do jogador, em que o jogador usa o recurso e, em seguida, cada orc referenciará esse recurso para identificar o alvo do jogador assim que ele aparecer no mundo do jogo Isso teria alguns benefícios extras de poder trocar, digamos, o alvo do jogador por todos os inimigos trocando o recurso uma vez Poderíamos até mesmo fazer com que o sistema de combate definisse a referência assim que eles colocassem uma cópia do orc na cena do jogo Portanto, o sistema de desova pode essencialmente escolher qual jogador cada orc escolherá, e isso pode ter alguns benefícios adicionais em relação a simplesmente torná-lo uma referência única de dez, que você certamente poderia fazer, neste caso, pelo Mas isso também o vincularia estritamente a um jogo para um único jogador, o que é bom para este curso. Mas vou tentar mostrar como você pode conseguir isso com o método de recursos. Então, no canto inferior esquerdo do nosso sistema de arquivos, vamos derrubar tudo. E vamos entrar nos personagens, e eu vou clicar com o botão direito aqui, criar um novo roteiro. Vamos chamar esse jogador de contexto. E para heranças, vamos torná-la um recurso. Ok, crie o novo script e certifique-se de abri-lo no editor de scripts que fornecerá o contexto do player ao nome da classe. Ok, então isso é apenas configurado para ser essencialmente uma referência compartilhada a um jogador específico dentro do jogo. Então, o que precisamos aqui será var player. E se tivermos uma classe de jogador, faremos com que ela estenda isso. Então var player é do tipo player, e isso pode realmente ser tudo o que realmente precisamos aqui. Para esse recurso. Então, vamos ao script do player agora, e dentro do player, vou exportar uma referência para o contexto. Então, vamos fazer um contexto Export var, e vou chamar isso de contexto do tipo player context, controles para salvá-lo. E podemos ver no momento que temos um espaço para recursos. Então, vamos criar nosso novo recurso. E então eu quero clicar com o botão direito e salvá-lo no projeto. Vamos salvá-lo em, digamos, personagens. Poderíamos colocá-lo no player se quisermos, então por que não? E então eu vou chamá-lo player Context aqui dot TRS, que é para recursos Você também pode querer mover o contexto do jogador no GD para o diretório do player com barra de caracteres Ok. E agora nossos orcs precisam de um alvo. Então, podemos ir até o NPC orc. Você pode clicar aqui se precisar. Diremos que em Export var target é um contexto de player de tipos. Se precisar, você também pode transformá-lo um contexto de destino se precisar dar um passo mais genérico para isso, mas eles sempre terão um alvo. Então, acho que tornar mais específico chamando-o contexto do jogador pode ser um pouco melhor aqui para nosso caso específico. Mas sinta-se à vontade para torná-lo um contexto-alvo se quiser que os inimigos persigam objetos inanimados, NPCs ou algo parecido E isso vai conter a referência ao jogador alvo que esse NPC está perseguindo Então, vamos colocá-lo diretamente no inspetor. Então clique em OC e, no lado direito, precisamos dar a ele o contexto do jogador. Então, vou clicar aqui. Carregamento rápido, contexto do jogador. E você notará que, embora o orc e o jogador sejam duas cenas completamente separadas, podemos fazer com que eles façam referência ao mesmo recurso e ao nosso projeto O recurso existe no sistema de arquivos, então podemos referenciá-lo nossas cenas individuais empacotadas. Então, quando eles realmente forem adicionados ao mesmo cenário mundial do jogo, ambos terão a mesma referência. Então, o jogador se definirá como jogador no contexto do jogador e, em seguida, todo o resto, os NPCs lerão isso E é assim que eles vão se relacionar uns com os outros por meio desse intermediário de contexto Portanto, o script do NPC não fará nada diretamente aqui Vamos configurar isso no estado de Chase. Mas a última coisa que precisamos fazer antes de chegarmos ao estado de perseguição é voltar à cena do jogador e voltar para dentro do jogador pronto. Primeiro, queremos afirmar que o contexto não é nulo porque é meio que necessário para o nosso jogo Portanto, afirme o contexto para que o recurso precise ser definido aqui para que o jogador possa se tornar o jogador do contexto E então vamos considerar o contexto: dot player é igual Na verdade, isso vai ao ar qualquer maneira, assim que não tivermos um contexto, porque não pode ser nulo Portanto, essa afirmação pode nem ser necessária. Podemos simplesmente cortar isso e reduzir a redundância. Então, desde que tenhamos essa linha e o jogador carregue primeiro, o jogador no contexto está definido e, em seguida, carregamos todos os outros NPCs, podemos fazer com que eles usem seu estado hace para se moverem em direção ao jogador Então, dentro de Ok, vamos para o estado de Chase. Então, no estado de Chase, precisamos obter essa referência ao jogador. Então, podemos obter isso como uma referência ao orc, e então o orc tem o contexto do jogador aqui Portanto, algumas etapas foram removidas. Então, vamos ver. Talvez digamos algo como alvo de VR, nó dois D aqui. Então, temos essa variável local. E então, sempre que entrarmos, no estado de Chase, obteremos uma referência a esse alvo. Você pode até mesmo fazer isso na configuração, se quiser que seja uma coisa única. Vou colocá-lo em Enter. Então, toda vez que entrarmos no estado, obteremos o novo alvo do contexto do jogador. Portanto, o alvo sublinhado é igual ponto-alvo do agente Como não sabemos qual é o tipo de agente do NPC, não sabemos se ele tem o alvo e não sabemos se o alvo tem um jogador Ok, então essa parte é um pouco frágil porque basicamente pressupõe que o agente é um NPC, pressupõe que o alvo está definido e presume que o jogador ainda é propriedade do contexto do jogador para obter Portanto, essa linha, especificamente, pode ser quebrada facilmente se você mudar algumas de suas outras classes. Talvez você queira apenas configurar algumas afirmações aqui também para serem apenas sinais de alerta precoce Então, poderíamos dizer afirmar o agente ponto-alvo e talvez afirmar o agente ponto-alvo alvo jogador Vamos mudar isso de agent dot Target para agent dot Target é um NPC Ok, e eu acho que isso é bom o suficiente. Não abrange todos os casos, mas se mudássemos essa classe para outra completamente diferente, acho que essas duas linhas entenderiam isso. Vamos clicar em Play e ver se ainda estamos bem ou se temos algum problema aqui. Então, esperava-se que o agente fosse um NPC. Talvez o que eu queira seja o agente Target como NPC. Talvez eu esteja apenas usando a palavra-chave vinculada lá. Então, aqui, eu realmente quero verificar se o agente é um NPC O agent dot Target é o contexto do jogador. Portanto, garantimos que o agente seja um NPC para que possamos operá-lo nele E não estamos tendo problemas agora. Então isso é bom. E a última coisa que precisamos fazer é mover em direção ao local de destino, e faremos isso na atualização do sublinhado da função Então, vamos implementar isso. Ok, então precisamos obter a posição do alvo. Até agora, posição alvo. Ok, então isso será atribuído a partir da posição global do ponto alvo do sublinhado E então temos a posição do nosso agente. Até a posição do agente. Isso será igual à posição global do ponto do agente. Então, um agente pode tecnicamente ser um nó normal, eu acho, e é por isso que ele não aparece aqui Posição de agente da Savara. O motivo pelo qual não é possível inferir o tipo é porque não sabemos com certeza se o agente tem essa propriedade de posição global Então, precisamos declará-lo lá como um vetor dois. Ok, e então queremos obter a direção entre esses dois locais. A direção de Savara será igual à posição alvo menos a posição do agente E então normalizamos esse vetor para obter apenas uma direção Portanto, ele normaliza o valor XY para uma escala de 1,0. Não terá mais nada parecido com a distância. Será apenas a direção do par, que seria muito parecida com se você estivesse inserindo um vetor de ponto a ponto para a entrada do teclado Isso também estaria em uma escala de 0 a 1 para X e Y. Ok, agora que temos a direção, só precisamos nos mover na velocidade que estamos atribuindo Então, cada um de nossos personagens terá uma velocidade no jogo, e vamos obter essa velocidade nosso controlador de estatísticas Então, acho que uma boa maneira de configurá-lo seria usar o Blackboard Então, se eu clicar em Enemy HSM, podemos acessar o plano Blackboard, vamos gerenciar e adicionar uma variável Vamos ver as estatísticas. Isso pode ser um caminho de nó e, em seguida, atribuiremos o controlador de estatísticas. Então, agora podemos usar isso em, digamos, nosso script Chase e obter a velocidade dele. Então, na configuração, queremos obter esse controlador de estatísticas. Portanto, podemos dizer que var, underscore stats é um controlador de estatísticas, e diremos que as estatísticas de sublinhado iguais a Blackboard dot Git var, e estamos procurando Então, a partir daí, queremos obter a velocidade. Então, var speed aqui na parte inferior novamente, que é uma flutuação, será igual a underscore stats dot Get Ou, se quisermos tornar isso ainda mais simples, podemos dizer apenas a velocidade dos pontos Então, agora precisamos de uma velocidade de tempo de execução para as estatísticas do nosso personagem. Então, entramos no controlador de estatísticas e vamos criar uma propriedade de velocidade aqui. Então, para velocidade, um flutuador é igual a 100,0. Então, essa é basicamente a velocidade de execução do personagem em tempo de execução. Ainda não configuramos nenhum recurso de definição para controlar basicamente quais serão as estatísticas iniciais de cada personagem, como o orc ou a dama, que colocarão em um esqueleto Então, estamos apenas construindo isso um passo de cada vez. Então, agora no Chase State, temos nossa direção, temos nossa velocidade, temos nosso Delta, então só precisamos mover o personagem uma certa quantidade. Então, quando você move o corpo de um personagem em dois D, há pelo menos duas maneiras de fazer isso. Uma seria chamar Move and slide, e isso seria no NPC Então esse agente é coisa de NPC aqui em cima, acho que seria melhor se fizéssemos Var NPC do tipo NPC E, em vez disso, dizemos que sublinhado NPC é igual E então afirmamos que esse NPC não é nulo. Portanto, isso garante que o agente seja um NPC, mas também temos uma referência ao NPC para que possamos usar suas funções de classe Então, fica mais fácil vir aqui e dizer coisas como NPC dot MOV e slide Você pode usar isso, e isso também teria a capacidade de deslizar ao longo de qualquer colisão que os inimigos Mas vamos fazer com que nossos inimigos ignorem a colisão neste jogo, parcialmente porque ela permite que você coloque mais inimigos na tela, e também parcialmente porque simplifica as coisas, mas na verdade vou fazer o npc dot Portanto, isso permite que você se mova sem levar em consideração a colisão Portanto, tem a desvantagem de seus personagens não conseguirem deslizar bordas como a beira da água uma árvore ou coisas assim que estão atrapalhando Mas também tem a vantagem de tornar o movimento o mais simples possível, o que significa que você pode colocar mais inimigos na tela ao mesmo tempo E eu acho que talvez isso se encaixe um pouco mais no estilo de um vampiro sobrevivente Então, vamos simplificar a morte cerebral de nossos inimigos. Então pc dot translate, estamos apenas movendo-o em uma direção em uma quantidade. Então, fazemos direção vezes velocidade vezes Delta. Agora, isso funcionaria bem, mas talvez você queira levar esse bit para mais uma variável acima e salvar nosso movimento, que é do tipo vetor dois, e definiremos isso como igual a esse bit aqui. Então, fazemos a matemática fora da chamada da função e, em seguida, a chamamos no vetor de movimento dois quando temos isso. Isso também ajudaria na depuração pois você pode definir um ponto de interrupção e, em seguida, mostrar qual foi o valor da movimentação antes de você chamar translate Caso contrário, se você simplesmente colocasse isso lá, você não saberia o que está acontecendo na chamada de tradução, a menos que entrasse aqui Então, um pouco mais limpo, um pouco mais fácil. Ok, então eu vou clicar em play, e vamos ver onde estamos. Temos os orcs correndo em direção ao jogador, e onde quer que o jogador esteja na tela, eles tentarão ir até lá, o que é exatamente o que esperaríamos Agora, eles se movem bem rápido, então eu poderia entrar no Stack Controller e levar a velocidade padrão para algo como, digamos, 40,0 e em jogo Ok, e eu acho que isso é um pouco mais apropriado. Na maioria dos casos, o inimigo deve se mover mais devagar do o jogador para que o jogador tenha pelo menos a chance de evitá-lo. Podemos ver que eles estão todos empilhados uns sobre os outros Ok, então clicaremos em play e veremos que os orcs correrão em direção ao jogador Essas árvores não têm nenhuma configuração de colisão, mas mesmo que tivessem, elas ainda correriam direto pelo corpo do jogador Agora, o jogador também está colidindo com os orcs. E isso porque os orcs ainda têm a forma e o corpo de uma colisão, e o jogador está se movendo usando o movimento e Então, depende de nós para onde queremos ir a partir daqui. Poderíamos mover todos os orcs para uma camada de colisão diferente usando a colisão E eu provavelmente faria isso agora. Vamos configurar algumas camadas de colisão. Portanto, edite os nomes das camadas. Diremos que um é mundo, dois é jogador, três é inimigo, quatro é projétil, e isso deve ser bom por enquanto. Vamos fechar isso. Então, queremos mover nossos inimigos para a camada inimiga e desligar a máscara para que eles não queiram realmente colidir com nada no momento Então, agora, se clicarmos em play, nosso jogador será capaz de atravessar os inimigos, mas ainda assim colidirá com qualquer outra coisa. Então, na verdade, eu realmente não gosto que eles se sobreponham Portanto, embora o Translate seja a função mais rápida de ser executada aqui para o estado Chase. E esse é definitivamente o conjunto de linhas de código que será o obstáculo de desempenho do projeto porque você terá centenas de potencialmente até milhares, de inimigos tentando se mover ao mesmo tempo usando esse script de atualização. E lembre-se de que quase todos os inimigos estarão no estado de Chase o tempo todo até serem realmente derrotados, e só serão derrotados por um segundo. Então você está falando sobre tudo estar no estado Chase ao mesmo tempo em que a atualização é executada em todos os quadros. Então, essa é a parte em que, se você precisar otimizar alguma coisa, seria isso. Vamos adicionar novamente a colisão para os orcs. Faremos com que eles colidam consigo mesmos e veremos se isso nos dá um resultado melhor Os orcs estarem todos em cima uns dos outros não é realmente o ideal Então, vamos colocar isso de volta. Então, em vez de fazer NPC dot translate, o que fazemos é dizer que o underscore NPC Velocity será igual a esse bit Então, vou me livrar do Delta e vamos dizer nova velocidade Ok. E então ajustamos a velocidade antiga para a nova velocidade E então, em vez de chamar NPC dot translate, chamamos npc dot move e slide Mais uma vez, quero repetir que isso consome cerca de duas vezes mais poder de processamento dos meus testes Então, se você pudesse ter 5.000 inimigos na tela ao mesmo tempo antes de perder o atraso, agora serão cerca de 2.500 Mas se você conseguir que os inimigos se distanciem, talvez não precise de 2.500 inimigos na tela ao mesmo tempo, porque todos eles ocupam uma posição completamente diferente Então, talvez esse seja o caminho a percorrer. Então, vamos até a orca e faremos com que ela mascare o inimigo Também colidirá com o jogador aqui. Então, está olhando para o jogador, o inimigo. E também vamos fazer disso o mundo, mas não projéteis. Ok. E então queremos ir até o jogador agora que na verdade estamos trabalhando com diferentes camadas de colisão, e definiremos a camada de colisão que está sob a colisão Objeto dois D E então queremos que ele colida com o mundo. E, na verdade, acho que é exatamente isso. Pensando nisso novamente, os orcs, talvez eu não queira que isso colida com o jogador Quero que o jogador seja capaz especificamente de atravessar os inimigos para que ele possa realmente escapar. Assim, os inimigos colidirão com os inimigos e com o mundo, e começaremos a jogar a partir daí Poderíamos até mesmo desligar o mundo em algum momento. Depende do que queremos. Ok, então vamos ver. Parece que os inimigos não estão se acumulando uns sobre os outros, o que provavelmente é bom Eles não ocuparão exatamente o mesmo espaço. Se quisermos que eles fiquem ainda mais espaçados, aumentaríamos o tamanho dessa forma de colisão Aqui, se eu pausar o jogo bem rápido e acessarmos o Editor de formas de colisão visíveis, podemos voltar Oh, temos que reiniciar o jogo para isso, eu acho. Ok, vamos reiniciar e então poderemos ver as formas da colisão Então, essa aqui embaixo é a forma de colisão do orc O maior deles é o raio de impacto, então podemos atingi-los bem alto, mas eles só podem colidir aos pés, porque foi assim que definimos as formas de colisão Mas sim, com essa configuração, eles ficarão um pouco mais espaçados um do outro. E acho que estou gostando. 23. P22 Gerando inimigos em uma curva de tempo: Você pode ver nossos inimigos trabalhando. Eles terão uma pequena colisão um com o outro. O que, você sabe, depois de assistir esse é definitivamente o caminho a percorrer, em vez do método de tradução. No entanto, ainda temos apenas quatro orcs ao mesmo tempo. Queremos ser capazes de gerar um monte de caras e, se quisermos esse estilo de sobrevivente, queremos que eles apareçam fora da tela e depois sigam em direção ao depois Então, quase em um círculo, precisamos que eles apareçam fora da tela e , em seguida, coloquem o jogador no centro da tela Então, precisaremos de um sistema de desova para fazer isso. Vamos ao mundo e adicionaremos um novo nó do sistema aqui. Vou clicar com o botão direito do mouse em Adicionar um nó filho como nó e, em seguida, renomear isso para sistema de geração ou SponnorSystem, se você preferir ou SponnorSystem Clique com o botão direito do mouse e anexe um script. Então, vamos chamá-lo de sponsorsystem dot gD e eu vou salvá-lo na pasta systems E então, para nosso sistema de geração, precisaremos declarar várias propriedades diferentes que serão barras de exportação para que você possa personalizá-las no Então, primeiro, precisamos da margem de desova, que é uma flutuação, e eu vou defini-la como padrão para dez. Esqueci o carro lá Ok, então a margem de desova é a distância mínima da tela que os personagens podem gerar Isso está em pixels. Vou receber esse nome para serem personagens na verdade, e personagens de lá em cima também. Talvez tenhamos um mundo onde geramos NPCs, não necessariamente apenas inimigos Portanto, ajuda ser mais genérico quando você não tem certeza sobre o uso final do seu script, porque talvez você queira que ele seja mais flexível do que apenas matar inimigos. Ok, em seguida, queremos o alcance extra de spawn. Ok, então no Export VR span extra range, vou fazer com que chegue a 100. Ok, então essa é a distância adicional que um inimigo pode aparecer longe da borda da tela, além da margem de extensão Portanto, se sua margem de desova for dez e seu alcance extra for 100, isso significa que a distância em pixels da borda da câmera será de dez a 110 pixels Então, precisamos das definições de nossos inimigos que vamos gerar Portanto, isso deve ser basicamente uma configuração que diz o que pode aparecer sob quais condições Então, digamos que em export var random definitions, que é uma matriz de definição de desova. Ok, agora não definimos essa classe. Vai ser um tipo de recurso. É uma definição que configuramos no editor e que usamos durante o jogo. Portanto, um recurso é o tipo perfeito para esse tipo de dado. Ok, então isso vai nos dar um erro porque não temos o nome da classe de definição de geração Vamos fazer isso. Agora mesmo. Vou entrar na raiz do nosso projeto e do sistema de arquivos. Digamos que talvez isso pertença aos sistemas porque faz parte do sistema de desova. Vou clicar com o botão direito do mouse, criar uma pasta e diremos spawning E aí dentro, eu clico com o botão direito do mouse, crio um novo script e digo aqui gerando a definição de sublinhado, que é do Ok, crie isso e depois abra esse script. Ok, e precisamos dar um nome de classe, definição de geração aqui no topo, e nos preocuparemos em configurá-la um pouco mais tarde Então, para continuar com o sistema de desova, precisamos de um pai para onde realmente geramos nossos objetos Portanto, em Export var spawn parent é uma referência do nó dois D, o pai de qualquer objeto gerado pelo sistema E então queremos a frequência. Então, vou fazer disso uma curva para que possamos controlar o cronômetro. Conforme o tempo avança basta usar uma curva e, em seguida, fazer a amostragem da Então, em vez de definir dez períodos de tempo diferentes, após 30 segundos, apareça a cada 0,5 segundos. E depois de 60 segundos, spa a cada 0,4 segundos. Podemos apenas tê-lo como uma curva. E então, não importa quando esteja desovando, ele obterá a próxima quantidade de cronômetro a partir Então, se você vai ter muitos valores, é mais fácil definir uma curva com uma inclinação do que ir uma por uma e ser como se X então Y fosse um estilo mais de dicionário Então, eu vou dizer export var span frequency, que é do tipo curva. OK. Voltaremos a isso no inspetor Ok, a próxima coisa que vamos querer é uma variável de tempo de execução. Vou chamá-lo de var random span stats. E isso vai ser do tipo dicionário. Quero fornecer o tipo de chave do dicionário e um tipo de valor. E o tipo de valor são estatísticas de geração. Portanto, isso corresponderá ao tipo de desova às estatísticas da desova em uma proporção de um para um em tempo para um Então, isso é específico do tempo de execução, e isso é específico do editor. E as estatísticas de geração acompanharão quando foi a última vez que realmente geramos um objeto e quantas vezes geramos usando Então, vamos criar nosso objeto de estatísticas de geração. Vou clicar com o botão direito do mouse em spawning e criar um novo script. Vamos chamá-lo de estatísticas de desova. Na verdade, essa extensão será contada como referência. Agora podemos entrar no span Stats e, aqui em cima, vou dar a ele o nome da classe spatts E as duas coisas que eu quero rastrear aqui são a contagem de spawn, que é um número inteiro que começa em zero e a última hora de spawn, que é uma flutuação, e vamos começar no Essa será a última vez que o objeto será gerado. Ok, agora em nosso sistema de desova, temos essa relação Então, quando iniciamos o sistema de geração, queremos pegar as definições e criar uma nova estatística de amplitude para cada uma das Portanto, isso lida com os dados de tempo de execução. Isso trata dos detalhes do editor para nossa configuração individual aqui. Então, se quisermos obter as estatísticas de amplitude, podemos apenas referenciar a definição de amplitude, e ela imediatamente exibirá as estatísticas de amplitude que correspondem a ela as estatísticas de amplitude que correspondem a Em poucas palavras, é assim que os dicionários funcionam. Você tem uma chave e ela lhe dará um valor, e é muito útil para relacionar dois objetos diferentes. Então, vamos configurar nossa função pronta para o sistema. Então, digamos que a função underscore ready retorne nula E queremos dizer que, para definição em definições aleatórias, queremos pegar as estatísticas de desova aleatórias e atribuir a chave de definição ao nosso valor, que será uma nova estatística de desova Então, o spawn começa com um ponto em OK. E agora temos um desses objetos para cada definição, e eles estão vinculados em uma definição de um a um de geração como chave e estatísticas de amplitude como valor Então, agora fica muito fácil consultar as estatísticas de spawn para obter a definição Ok, digamos que o próximo tempo de desova seja igual à frequência de desova, que é a curva, e amostramos na curva o tempo decorrido desde o início do jogo Então, precisamos de mais algumas variáveis aqui, na verdade. Vamos precisar do tempo decorrido, que é o tempo desde que o sistema de desova entrou no Podemos criar uma variável de temporizador. Portanto, VarSpawtr é um flutuador do tipo zero, zero. Como esse será um cronômetro interno, não há problema em ter um nó gerenciando seu próprio controle de tempo Então, vamos tentar fazer isso com um sistema de amplitude em vez criar um objeto de cronômetro real no mundo do jogo Portanto, o sistema de desova administrará seu próprio tempo para essa instância E então, a próxima hora de desova do spa será basicamente quanto tempo estamos esperando pelo próximo spa Vamos configurar a função de cronômetro aqui, processo de sublinhado da função, e esse será Delta como parâmetro, retornará Vamos pegar o tempo decorrido e adicionar o Delta, que é o tempo desde a última chamada do processo Então, o tempo decorrido mais é igual a Delta. E então queremos pegar o cronômetro de desova e mais também ser igual ao Delta, já que estamos acompanhando há quanto tempo E diremos que o cronômetro de desova é maior ou igual ao próximo tempo de desova, então vamos fazer um Então, um intervalo aleatório aqui e, depois disso, usaremos o cronômetro de desova E em vez de definir isso diretamente para Zal, vou ser menos igual ao próximo tempo de desova, porque pode haver um pouco de tempo restante, especialmente se chegarmos a intervalos de tempo muito especialmente se chegarmos a Então eu acho que é um pouco melhor torná-lo mais preciso assim. E então diremos que a próxima hora de desova será uma amostragem da curva de frequência Então, é igual à frequência de geração da amostra de pontos, e estamos amostrando Então, basicamente, na curva XY, é um gráfico em que X é o tempo decorrido desde que o sistema entrou em cena E então Y é quanto tempo esperar pelo próximo período. Portanto, seja qual for o tempo decorrido, haverá um novo valor que podemos obter da curva para definir nosso próximo horário de desova Ok, mais algumas linhas, e vamos fazer nossa função de geração aleatória, até agora random span Tipo de devolução do vazio. Então, o que precisamos fazer é obter nossa definição de desova que queremos gerar Então, essa será uma seleção aleatória com base na ponderação de cada uma das definições para determinar qual objeto será estendido ou não gerado Ok, vou passar por aqui por enquanto porque a lógica da desova vai ficar um pouco mais complicada Eu só quero fazer com que possamos pelo menos vê-lo funcionando no mundo dos jogos por enquanto. Então, voltando em uma visão em dois D, vamos pegar o sistema de geração e atribuir esse bom pai ao nó inimigo. Está bem? Então, desse jeito, deveriam ser inimigos. Essa frequência de ligação será uma nova curva. Então, vamos seguir essa curva e podemos definir valores. Então, se você puder ampliar aqui, isso vai ajudar. O domínio Min no domínio Max será basicamente quantos segundos de jogo o temos. Então você poderia dizer algo como 300 segundos ou 120 segundos. Por mais longo que você ache que o nível deveria ser, isso seria o que você gostaria de tornar o domínio máximo. Então, se você tiver uma última vez para seu nível e depois disso, o nível terminar, isso seria perfeito para o domínio Max aqui. O valor X Y, o que queremos obter sempre que amostramos o valor X. Então, quanto tempo deve demorar entre os spawns? Talvez dois como valor máximo , então subimos até a curva e clicamos com o botão esquerdo para definir um ponto, e meio que controlamos isso. Então, em geral, no início de um nível, você gostaria de menos spawns do que no final Então, se colocarmos isso aqui e dissermos que, talvez apenas a cada 1,5 segundo, um personagem apareça, e então vamos para a direita e clicamos com o botão esquerdo e puxamos esse ponto do quadro-chave para algo assim, onde podemos dizer cada talvez não 0,2 Oh, talvez sempre 0,2 segundos. Então, a cada 0,2 segundos, um inimigo pode aparecer. E nós meio que temos essa curva daqui até aqui. Você também pode clicar nos pontos, e há um ajustador de curva se você precisar ficar um pouco mais sofisticado com Então, agora, se fizéssemos uma amostra, digamos que aos 75 segundos do início do nível do jogo, isso significaria que o tempo de desova seria de cerca de 1,2 Podemos ver isso de onde o XY se cruza na linha. Da mesma forma, se chegássemos até 225 , seria cerca de meio segundo entre a frequência de desova do inimigo Portanto, a dificuldade fica mais difícil à medida que o nível avança. E podemos simplesmente ajustar isso. Você pode até definir um terceiro ponto no meio, se precisar disso. Talvez você precise que fique achatado por um tempo e depois fique muito duro Controle E para desfazer. E acho que você pode clicar com o botão direito do mouse em um nó para removê-lo do gráfico. Provavelmente, dois pontos serão bons o suficiente, porque você pode controlar isso com as alças se precisar alterar essa taxa em que fica mais difícil. Mas nós poderíamos meio que fazer isso. Agora, vou pessoalmente seguir esse caminho aqui à esquerda, porque em nossos testes, eu realmente não quero testar depois de 2 minutos. Eu só quero acelerá-lo para que eu possa mostrar como isso vai funcionar mais tarde Mas em seu jogo real, fique à vontade para ter uma curva de desova muito mais longa Então, agora, depois de 120 segundos aqui, ele vai ficar plano para o resto. E isso é bom para mim agora. Ok, agora vamos criar uma definição de desova. Aqui em cima. Vamos adicionar um. Precisamos criar um novo recurso para a definição de desova. Então, nova definição de desova, vamos clicar com o botão direito do mouse e salvá-la Vamos falar sobre personagens, inimigos. E eu posso colocar isso na mesma pasta em que o orc está porque vamos chamá-lo de orc Definição de apenas desova de orcs. Acho que a desova de orcs é boa. Dot TR, sim, nós o salvamos. Mas é claro que isso ainda não tem nada associado. Então, precisamos adicionar qual cena lotada vamos realmente instanciar sempre que gerarmos Ok, então, na definição de spawning, script. Vamos adicionar a exportação do vR à cena, que é um tipo de cena compactada. E também podemos adicionar um peso variável de exportação, que será uma flutuação de 1,0 Portanto, temos a cena a ser gerada e a preferência de selecionar essa cena como opção aleatória de geração Então, quando selecionamos aleatoriamente, podemos ter três tipos, e cada um deles tem um peso diferente Então, se um tem um peso de três e o outro tem um peso de um, então aquele que tem um peso de três tem três vezes mais chances de ser selecionado como aquele que tem um peso de um. E essa é apenas uma maneira de torná-lo um pouco mais distorcido na aleatoriedade Portanto, não é perfeitamente aleatório. É que cada escolha tem um peso, e o peso determina as chances. No esquema da seleção aleatória. Então, clicamos no sistema de desova agora. Ok spawning agora terá uma referência de cena, então carregamos rapidamente nossa cena Ok Ok, agora isso nos dá o que precisamos. Então, para o spawn aleatório, vou simplificá-lo o máximo possível agora, obtendo a primeira definição na lista e, em seguida, instanciando-a Até agora, a instância, que será número dois, D é igual às definições aleatórias na posição zero. E nós vamos pegar a cena, e vamos instanciar isso Ok, então agora temos nosso Oc. Essa é a posição zero e a desova do orc. Então, vamos pegar isso e adicionar isso ao pai aleatório ou ao pai do spawn Então, gere o ponto pai e o filho da instância, faremos com que a instância vá para a posição 00 por enquanto Nos preocuparemos com seu posicionamento aleatório mais tarde. E então podemos ver que o gerenciamento de intervalos já é gerenciado aqui fora da função de geração aleatória Então, honestamente, isso pode ser tudo o que precisamos. Para fins de teste, vou pegar isso e passar cerca de 10 segundos aqui, só para que possamos realmente ver o aumento da desova, se funcionar, e clicaremos em play. Então, vamos ver. Temos algum personagem chegando às 00? Oh, sim, sim, eu posso vê-los ali mesmo. Ok, então aqui estão nossos orcs. Você pode ver que está surgindo cada vez mais rápido passar do tempo Então, basicamente, já atingimos o pico de desova de orcs, e nossas lanças podem simplesmente cortá-los porque nossa lança não tem contagem máxima de acertos, então é muito fácil vencer este Mas você pode ver como a curva faz com que possamos facilmente aumentar a desova com o passar do tempo, e esse é um recurso interessante que eu realmente gosto muito É muito melhor trabalhar com isso do que definir em 10 segundos, agora a taxa de desova é 1,0 e, em 20 segundos, agora é 0,9 Então, agora você pode simplesmente todos os valores de todo o tempo, basicamente, ser gerenciados por essa curva, e é muito mais fácil editá-los. Você perde a precisão, mas fica muito mais simples dar uma ideia geral do que você precisa para esses valores E você ainda pode, você sabe, clicar e definir valores absolutos. Então, nos pontos aqui, você pode ver que pode definir as posições XY exatas para esses pontos se precisar ser realmente técnico. Mas na maioria dos casos, como eu disse, apenas dois pontos em uma curva serão bons o suficiente. Portanto, ainda há muito a acrescentar ao sistema de desova, mas esse é um bom começo para o que precisamos 24. Parte 23 Gerando a tela com deslocamento calculado: Ok, então já temos nossa desova funcionando. Mas o problema é que os personagens estão surgindo apenas no ponto 00 em que realmente queremos que eles apareçam da câmera para onde quer que nossa câmera esteja olhando Então, sempre parece que eles estão vindo de algum lugar muito distante, mas, na verdade, eles estão vindo de um pouco longe do que podemos ver. E então eles vão nadar com o jogador em vez de desovar no ponto Então, vamos trabalhar nisso. Ok, então em nosso script do sistema Spanner, vamos voltar a ele em um intervalo aleatório Então, no momento, a desova aleatória não é muito aleatória. Vamos trabalhar para tirar o inimigo da tela. Portanto, precisamos obter um novo local para onde estamos gerando a instância Então, aqui embaixo, vamos adicionar uma posição de geração var. Então, isso vai ser um vetor dois. E vamos obter isso em Obter posição de desova fora da câmera Então, queremos gerar uma posição de amplitude que esteja fora da câmera. Então, isso envolverá um pouco de matemática e a janela de visualização atual da própria câmera. Então, vamos criar nossa função, Get span position, fora da câmera. Então, a primeira coisa que precisamos fazer é colocar o TD da câmera que está ativo no momento, o que nosso jogador humano real está vendo na tela, para que possamos ficar fora dela quando desovarmos Portanto, nossa câmera será igual a Get viewport. Então, basicamente, estamos vendo o que o jogador pode ver atualmente e vamos pegar a câmera duas D que o jogador está usando para ver a janela de visualização Então, temos acesso a essa câmera talvez até faça sentido marcá-la , talvez até faça sentido marcá-la como uma câmera dois D. Então, poderíamos fazer um guarda verificar se quisermos aqui, dizendo que se a câmera for nula, que provavelmente nunca deveria acontecer, mas, em teoria, se pudesse, então queremos enviar um erro dizendo que não há câmera, nenhuma câmera 2 D encontrada na janela de visualização Talvez isso possa ocorrer se, por algum motivo, você estiver usando uma câmera de três D e simplesmente não houver duas câmeras D. Acho que isso faria com que isso desencadeasse um erro. Então, é possível. Ok, então se isso ocorrer, então há um grande problema no jogo. Vamos apenas retornar o ponto zero do vetor. Isso acontece e enviaremos o erro e deixaremos o desenvolvedor descobrir : Ah, por que não há câmera no jogo. Ok, mas supondo que tenhamos uma câmera, podemos realmente fazer as contas Então, primeiro, queremos obter a posição central da câmera. Vamos fazer com que o centro da câmera VR seja um vetor dois, e queremos a posição global do documento da câmera para isso. Sim, sem mais nem menos. E então queremos o tamanho da câmera. Então, qual é o tamanho da câmera na dimensão X e na dimensão Y. Então esse deve ser outro vetor dois. Então, vamos dizer que o tamanho da câmera VR do vetor dois será igual ao vetor dois, e obteremos o tamanho da janela de visualização Então, obtenha o tamanho do ponto da janela de visualização e, em seguida, queremos dividi-lo pelo zoom da câmera Ok, então a razão para isso é que nossa câmera, especialmente em um jogo de dois D da Pixar, se eu clicar na câmera dois D aqui em cima, e depois olharmos aqui para o Zoom, você pode ver que nosso Zoom pode realmente pegar a janela de visualização e escalá-la em quatro ou cinco vezes para que possamos ver bem nossa Pixar É por isso que precisamos ter certeza que, mesmo que estejamos vendo, digamos, 12 80 por 720 pixels, se aumentarmos o zoom por um fator de cinco, tamanho da nossa câmera será realmente reduzido para esses novos valores com base no É por isso que precisamos fazer esse ajuste. Então, a seguir, temos a câmera VR reta, que é uma reta dois do tipo D ou melhor, reta dois. E essa é uma forma retangular que representa os limites da nossa câmera É baseado no tamanho. Então, para a matemática aqui, estamos construindo um novo retângulo fazendo o retângulo dois e E nosso primeiro parâmetro é o centro da câmera menos o tamanho da câmera E então multiplicamos isso por 0,5. E então, para a segunda dimensão, temos apenas o tamanho da câmera. Então, isso nos dá a caixa retangular apropriada que representa a câmera na tela Em seguida, queremos selecionar aleatoriamente uma borda que usaremos para gerar os inimigos Então nossa câmera é uma caixa, então ela tem quatro bordas, e podemos basicamente gerar nossos inimigos acima, abaixo, para a esquerda ou para a direita Então, queremos apenas escolher uma dessas arestas e, como queremos uma distribuição uniforme, faremos isso aleatoriamente. E então não há espera. Então, em essência, isso deve significar apenas que eles estão vindo de todas as direções de forma bastante consistente. Então, se dissermos var edge, vamos fazer com que seja um valor inteiro, e será igual a Rand I para Vamos dar quatro por cento? O sinal de porcentagem aqui significa resto, então é o resto da divisão por quatro, que significa que será zero, um, dois ou três, e esses representam nossas Ok, então precisamos de uma compensação. que distância da borda queremos realmente gerar nosso inimigo Não queremos que eles apareçam diretamente na borda, porque assim ficariam visíveis na tela quando entrassem no mundo do jogo, e isso pareceria meio estranho Então, digamos que var offset, e acredito que essa será uma flutuação, igual à margem de sublinhado da extensão mais Ok, então estamos basicamente gerando um flutuador aleatório aqui e vamos multiplicá-lo pelo intervalo extra de amplitude Portanto, F aleatório pode ser 0-1 0,0. Portanto, um valor de zero vezes o alcance extra do nosso intervalo nos dará uma distância extra de desova de zero E se for 1,0, dará 100 porque é isso que definimos para a propriedade span extra range. E se tivermos algo intermediário , obteremos algum valor de pixels de 0 a 100 Além de nossa margem de amplitude, nos dando a compensação total Ok, então vamos dizer a posição var spa, e isso será atribuído a um vetor 20 aqui. Em vez disso, zero é o limite máximo da constante. Ok. Adicione mais algumas linhas. E diremos que se a borda for menor ou igual a um, então estamos tratando isso como a parte superior ou inferior. Então, vamos pegar nossa vantagem e fazer uma declaração de correspondência com ela para que possamos calcular a posição do filho com base na aresta que estamos realmente usando. Então, digamos que match edge e, padrão, enviaremos um erro resolvido Número da borda, porcentagem x vantagem percentual. Então, ter isso é meio que útil se esquecermos de, por algum motivo, colocar uma das caixas. Agora, podemos realmente combinar o número inteiro da borda com um valor Enum se quisermos ser um pouco mais descritivos verbalmente Então, se subirmos até o topo, declararei um enum, digamos, borda enum, e teremos o topo como zero, o fundo como um, a esquerda como dois e a direita como três Ok, então agora, se formos até aqui e combinarmos a borda com esses valores, poderíamos dizer borda ponto acima, se eu não estiver errado. Espere um minuto. Parece que há um pequeno problema aqui. Ainda assim, preciso colocar um sinal de igual aqui para o reto da câmera. Ok, então isso vai funcionar. Agora podemos descer até onde estávamos fazendo a correspondência do Enum e queremos realmente inserir o código aqui Portanto, a posição de desova X para o topo será igual a uma flutuação aleatória de um intervalo Então, dizemos intervalo de sublinhado Rnf, e vamos da posição do ponto do retângulo da câmera ponto X para a posição ponto da câmera ponto X mais o tamanho do ponto da câmera ponto X. Então, para um retângulo tutti, a posição X sempre estará aqui em cima Então, se você adicionar o tamanho X a isso, você virá aqui no lado direito. Então, se vamos para o topo, queremos nos posicionar em algum lugar entre aqui e aqui. É por isso que pegamos o valor aleatório da posição e depois a posição mais o tamanho. Então isso nos permite chegar em algum lugar entre essa linha aqui. E então precisamos fazer a posição Y, é claro. Então, a posição Y do spawn será igual à câmera Rect. Posição do ponto, ponto, Y. Menos o deslocamento Então, estamos subtraindo o deslocamento porque quando você subtrai um valor Y, na verdade você está subindo na tela Então, temos a posição Y, que é o topo do nosso retângulo Então, deixe-me tirar a tinta aqui. A posição Y está aqui em cima, certo? Mais especificamente, seria o valor Y que nos levaria ao ponto 00 no retângulo Então você pega o deslocamento, que será algum valor aleatório aqui em cima Então, nosso inimigo vai meio que aparecer nessa área, grosso modo, e isso se baseia em qualquer que seja o deslocamento Y gerado aleatoriamente Então, temos nossa margem de dez pixels, e então temos 110 pixels aqui em cima como nossa área extra de margem positiva, e então nossos inimigos podem aparecer em algum lugar dentro daqui para obter o valor máximo Ok, espero que isso faça sentido. E então nós meio que fazemos a mesma coisa para todas as outras bordas. Então, borda com pontos na parte inferior. Vai ser exatamente essa formação aqui. E então a posição Y do vão ser um pouco diferente. Então, queremos que o ponto Y da posição de geração seja igual reto da câmera, ponto Y, mais o tamanho do ponto reto da câmera, ponto Y. Então, isso nos leva à parte inferior do retângulo. Então, isso nos leva Porque agora estamos adicionando o tamanho Y, que nos puxa para essa área inferior E então adicionamos o deslocamento a isso. Então, acrescente o deslocamento e observe que estamos adicionando o deslocamento porque queremos ir mais abaixo da caixa da câmera, mas na parte superior, subtraímos o Isso é muito importante. Agora fazemos a mesma coisa com a esquerda e a direita. Então, ponto de borda à esquerda, que são nossos dois enum. E isso será a posição de geração: ponto X igual, ponto reto da câmera, ponto ponto y menos o deslocamento, porque estamos indo para a esquerda em nossa caixa, então queremos Isso é tudo para a posição X do spa, e é o POS do spa, não a posição do spa. Eu o abreviei Então, o poste Y do spa agora será igual a, e pegamos um intervalo F aleatório entre o retângulo da câmera ou o retângulo da câmera, posição do ponto Y. Então essa será a parte superior da nossa caixa E então o outro lado do aleatório será o fundo da nossa caixa. Então isso vai ser a posição do ponto destruído da câmera, ponto Y, mais o tamanho do ponto destruído da câmera, ponto Y. Então, quando adicionamos o tamanho, mais uma vez, vamos Portanto, nossa posição vertical do vão para a esquerda e para a direita está em algum lugar nesta linha aqui E, finalmente, pontuar para a direita em maiúsculas. Ele terá a posição de amplitude X da câmera, posição do ponto reto, ponto X mais a câmera, nós dimensionamos o ponto X mais o deslocamento Então, a mesma coisa. Temos uma caixa aqui e uma caixa aqui, e queremos deslocar para a direita ou para a esquerda se estivermos gerando para a esquerda Deixe-me verificar isso. Ok, posição X mais ponto de tamanho X mais deslocamento Ok, isso parece correto. Claro, vamos testá-lo no jogo. E então a posição Y do vão deve ser a mesma porque ainda estamos lidando com essa vertical escolhendo um ponto aleatório entre aqui e aqui e aqui para a geração esquerda e direita Ok, então esse deve ser basicamente nosso código de posição de amplitude. E então queremos retornar a posição do vão. Portanto, essa função está boa do jeito que está. Não é tão ruim. Se ficasse um pouco maior, eu provavelmente o levaria para outra função. Honestamente, poderíamos porque senti a necessidade de colocar esse comentário no código Então, se eu quisesse, poderíamos dizer função, sublinhar, calcular a geração final, que retornará em um vetor dois E então colocamos isso aqui em vez de padronizá-lo para o vetor dois e colocar tudo isso aqui embaixo. E reduzimos isso para nossas novas funções, então estamos refratando E então, obviamente, exigiremos que alguns parâmetros entrem nessa função para que ela funcione. Então, primeiro, precisamos, digamos, câmera rect, que é um retângulo dois, e então precisamos do tamanho da câmera, que é um vetor dois Control S. E então queremos retornar a posição do filho dentro daqui Portanto, a posição de geração de var é um tipo de vetor dois. Descemos até o fundo e retornamos a posição do spa daqui. Está bem? Aqui em cima, queremos passar esses parâmetros, então a câmera reta e o tamanho da câmera E então precisamos disso aqui. Finalmente, também precisamos do deslocamento. Então, passe o offset aqui em cima. Ok. E então precisamos de offset como parâmetro Então, offset, e acho que também era um vetor dois. Está bem? Então, o Control S, na verdade, era apenas um fluxo? Oh, era um carro alegórico. Ok. Então, um flutuador unidirecional E depois de salvar esse, a maioria desses erros deve desaparecer. Então, precisamos combinar na borda e depois voltar. Também poderíamos inserir esse parâmetro de borda. Então, edge, que vai ser do tipo. Na verdade, poderíamos usar o enum aqui. Deve funcionar bem porque o número inteiro pode ser atribuído automaticamente a um enum, até onde eu sei Então, se subirmos até aqui e passarmos pela borda, ok, vai entrar aqui e vai funcionar como uma enumeração, que é mais ou menos o que esperamos encontrar aqui embaixo Então, para examinar um pouco os enums, um Enum é basicamente uma lista de valores nomeados que correspondem à posição inteira dentro desse Então, o zero, porque esta é a primeira, é a posição zero. Então, é como o primeiro item em uma matriz. Você quase poderia pensar assim. E então o fundo é um, a esquerda é dois e a direita é três. Acho que algumas linguagens permitem que você atribua valores inteiros personalizados a um Eenum Não sei se você pode fazer isso no GdCrip, mas essa é basicamente a ideia Se você não mexer com isso , zero é o melhor. Um fica na parte inferior, dois esquerda e três na direita. Mas o que isso lhe dá a vantagem de fazer é que, quando você cria uma função como essa, em vez de dizer zero, um, dois, três, que é muito obscuro para o que isso realmente representa, o que é um Você pode simplesmente substituir isso por edge dot top, que é o valor de zero, mas fica muito mais claro para alguém que está lendo o código o que isso realmente deveria representar Ok, vamos ver. Então, temos nossa posição Get spawn fora da câmera, e a tivemos aqui em um intervalo aleatório Então, agora, na verdade, precisamos definir a posição para a instância. Portanto, a posição global da instância será igual à posição de desova Essa parte é fácil. Vamos clicar em Play e ver se realmente funciona. Porque isso era um pouco de código. Ok, então nossos personagens não estão aparecendo na tela. Eu os vejo saindo da tela. Vamos ver, ou qualquer um vindo de baixo e da direita. Não vejo nada vindo de cima ou da esquerda, e isso meio que me preocupa um pouco. Então, vou ver se consigo encontrá-los. Ok. E acho que o que devemos fazer para testar isso. Vou fechar o jogo agora mesmo é descer até aqui e estávamos sentindo falta deles na parte superior e na esquerda. Então, vamos adicionar um ponto de interrupção aqui e um ponto de interrupção aqui. Então, se, de fato, os personagens estão tentando aparecer do topo e da esquerda, eles devem aparecer. E então podemos verificar os valores que eles estão realmente atingindo. Então eu esqueci de parar no jogo, então ele atingirá automaticamente esse ponto de interrupção Clique em Play e veja se podemos obter um da esquerda. Ok, lá eu vi um vindo de cima, na verdade. Ok, e um está vindo da esquerda, supostamente. Então parece que está meio que acontecendo, certo. Talvez se eu aumentar muito a taxa de desova, seja mais fácil ver com certeza Então, vamos para o mundo. Temos o sistema de chave inglesa? Vou pegar isso aqui mesmo. Vou me lembrar do valor. Então, eram 0,66 e 1,5, e vou descer até aqui para que possamos ter uma desova muito rápida por enquanto Vamos clicar em Play e eu vou testar. Então, vamos ver um monte de caras surgindo muito rápido ou deveríamos E sim, ok, isso parece quase correto. Podemos pegar um cara do canto inferior esquerdo aqui? Porque eu quero ver isso acontecer também. Ok, sim, sim, finalmente, finalmente. Temos alguns caras lá. Ok, então eu acho que está funcionando corretamente. Se houver algum problema, é possível que a matemática não tenha sido verificada duas vezes para estar correta, mas acho que está indo do jeito que deveria. Se não, é um pouco difícil dizer. Mas sim, eu os vejo vindo de todas as direções. Então eu acho que estamos bem aqui. essa matemática seria algo muito No entanto, essa matemática seria algo muito fácil de errar, então vou colocá-la na tela mais uma vez se você precisar verificar novamente. Então, temos nossa posição de desova. Estamos obtendo isso da posição G spawn fora da câmera. Essa é a nossa função aqui. Então, obtemos o centro da câmera a partir da posição global da câmera, o tamanho da câmera é do tamanho da janela de visualização, e então você divide isso pelo zoom da câmera O retângulo da câmera é construído a partir do centro da câmera menos o tamanho da câmera vezes 0,5 e, em seguida, o valor Y para isso é apenas o tamanho da câmera A borda é um número inteiro aleatório e você obtém o restante de quatro, que lhe dará de zero a O deslocamento é a margem do intervalo mais F aleatório vezes o intervalo extra do intervalo Então, isso está em algum lugar de 0-1 ponto com pontos decimais, e então adicionamos o intervalo extra de amplitude como uma porcentagem Calcule a extensão final usando todas as propriedades que acabamos de configurar: o reto da câmera, o tamanho da câmera, o deslocamento e a borda Então, vamos colocar isso aqui. Nós combinamos no limite. Então, zero, um, dois e três. E então, para o valor X na parte superior e inferior, fazemos um intervalo aleatório entre o lado esquerdo e o lado direito. Usando essa matemática. Para a posição Y, tomamos a posição Y na parte superior e subtraímos o deslocamento ou, para a parte inferior, adicionamos o tamanho para chegar à parte inferior e, em seguida, adicionamos o E então, para a esquerda e para a direita, fazemos a mesma coisa ao contrário. Então, para X, fazemos o lado esquerdo menos o deslocamento, nos dando mais para a E então, para o lado direito, adicionamos o tamanho à posição X para obter o lado direito e, em seguida, adicionamos o deslocamento para ir mais para a direita a partir disso Então, para a posição Y do vão, fazemos um intervalo aleatório entre a posição, que é a posição zero Y, e depois a posição mais o tamanho, que nos dá a posição do canto inferior no eixo Y. E isso fará com que o spa esquerdo e direito estejam em algum lugar entre a parte superior da tela na vertical e a parte inferior da tela na vertical Mas a posição está deslocada da tela, então não vamos realmente vê-los aparecendo. E retornamos a posição do intervalo que possamos usá-la nessa outra função, e isso praticamente encerrará tudo. 25. Ladrilho 24 — gerador de inimigos aleatório com condições de peso e tempo: Nossa desova fora da tela está funcionando, essencialmente. Há algumas coisas que eu quero limpar e, em seguida, continuaremos adicionando um inimigo esquelético para que possamos selecionar aleatoriamente qual inimigo criaremos com base em um sistema Então, vamos encerrar o jogo. E primeiro, podemos ver esse rótulo aqui, a instância de texto de combate flutuante. Não precisamos mais disso porque terminamos de editar a animação. Então, vou deletar esse nó. E então, no sistema de desova, para a demonstração, eu baixei esse valor mais baixo do que era Então, aqui no primeiro ponto, eu queria trazer isso de volta ao original, que era tipo, acho que originalmente eram 0,66 segundos e depois 1,5 Vou fazer com que 0 segundos e depois 1,5 segundos seja o período de desova. Então, na verdade, podemos simplesmente ir até aqui e digitar 1,50. Pressione Enter, se quiser ser preciso com a configuração, e você pode ver que o ponto selecionado mostra 0 segundos e, em seguida, 1,5 segundo como o tempo de geração 0 segundos é o tempo decorrido aqui, se você se lembra. Acho que esses quatro inimigos do trabalho, poderíamos simplesmente remover da cena. Então, vou excluí-los. Então eu vou selecioná-los, clique em OK. Você pode clicar em play apenas para testar se tudo ainda funciona, e devemos fazer com que os inimigos saem da tela venham em nossa direção Não temos. Você pode clicar em play se quiser verificar novamente e apenas garantir que os inimigos ainda estejam surgindo Nós simplesmente não precisamos desses inimigos iniciais porque os inimigos virão depois que o jogo começar. Queremos dar ao jogador alguns segundos para, você sabe, se familiarizar com os controles e assim por diante Ok, então para criar o inimigo esqueleto, vamos primeiro clonar o orc que Então, vou pesquisar o orc e o projeto. Vamos até Orc Dot TCN. Vou clicar com o botão direito do mouse e cloná-lo, então duplique. Vou chamá-lo de Skeleton Dot TCN. E então vamos pesquisar no projeto aquela cena de esqueleto que acabamos de criar Clique duas vezes nele. E então vamos ampliar aqui. Então, vou pegar o sprite aqui e alterá-lo para o sprite esqueleto Então, vamos dar uma olhada rápida na direita, e vamos procurar o ídolo, e deve haver um para o esqueleto Talvez precisemos ampliar um pouco. Deveria haver um aqui para um inimigo esquelético. E então, no canto superior direito, podemos carregar rapidamente, e talvez você precise ampliar um pouco para encontrá-lo, mas digite idle e procuraremos a planilha de sprites esqueleto Pode ser um pouco difícil de ver, mas vou selecionar esse aqui. Se você não conseguir encontrá-lo, fique à vontade para navegar pelo sistema de arquivos e encontrá-lo. Provavelmente está na pasta base do esqueleto. Ok, agora vamos renomear o nó raiz para esqueleto. E precisaremos configurar o reprodutor de animação para garantir que ele reproduza as animações de idle skeleton e, em seguida, Ron skeleton e skeleton death Então, vamos ao reprodutor de animação. E então, no canto inferior direito, basicamente precisamos alterar a textura de cada um deles. Assim, a textura redefinida irá para o canto superior direito e, em seguida, carregará rapidamente a folha de sprite Idle que acabamos No momento, ele já está pré-selecionado, então podemos selecioná-lo. E talvez você queira jogar e garantir que ele ative, reinicie o esqueleto e, em seguida, altere a textura das outras animações Então, Idle, vamos clicar na textura, ir para o canto superior direito Carga rápida, escolha a folha de sprite pela terceira vez. Ok, e clique em Play. E então certifique-se de que está sendo reproduzido corretamente. Parece bom. Vamos para a animação da morte. Selecione a textura aqui. E como há muitos quadros no canto superior direito, é um pouco difícil realmente ver o que está acontecendo, ainda mais difícil do que a animação ociosa Então, acho que seria mais fácil simplesmente navegar até a arte e depois encontrar o pacote gratuito do Pixel Crawler, entidade, multidões, tripulação básica, morte base e, em seguida, arrastar a folha da morte para o canto superior direito desse jeito para o canto superior Ok, aperte play e verifique se está tocando corretamente. Então, parece que há oito quadros de animação aqui. Portanto, precisamos ampliar um pouco assim e garantir que os quadros H sejam definidos no canto superior direito para oito. Ok, então clique em Play. Sim. Ok, isso parece correto. E agora precisamos adicionar o sétimo e o oitavo quadros-chave Então, clique com o botão direito no quadro em 0,6 segundos e insira a chave, clique nela, vá para o canto superior direito, mude para seis, faça a mesma coisa em 0,7. Você não pode fotografar lá porque precisamos estender a animação Portanto, faça com que a animação tenha 0,8 segundos de duração. Clique em 0,7, S nesse quadro-chave e altere-o para sete, pois a oitava posição é o que queremos. Ok, vamos clicar em Play. Jogue mais uma vez. Aqui está nossa animação. Agora mova o estado de morte concluído até o final em 0,8 segundos, e aí está nossa animação de morte. Ok, então nós queremos correr. Deveria ser mais rápido. Clique na textura. E então, no canto inferior esquerdo, onde diz base esquelética, escolha a pasta de execução, a planilha de execução no canto superior direito Deixe isso aí. Clique em play e podemos ver que está reproduzindo nossa animação de corrida. Tem as mesmas faixas etárias, então é tudo o que precisamos mudar. Ok, esse é o básico do nosso esqueleto. Podemos ir até o controlador de estatísticas. Além de atribuir estatísticas, é como velocidade de corrida, HP e assim por diante para nosso esqueleto e valores personalizados para nossos orcs e CD, que são a configuração básica nossos dois personagens Então, vamos voltar ao mundo, e então teremos o sistema de geração, certo Então, temos nossas definições aleatórias aqui à direita. Queremos adicionar outra definição aleatória e, em seguida, vamos criar uma nova. Então, nova definição de desova. Digamos que o peso do esqueleto seja 0,5, então teremos metade dos esqueletos dos orcs E vamos carregar rapidamente a cena do esqueleto, ok? E então vamos verificar o script do sistema de patrocinadores. Então abra isso e veremos a seleção aleatória aqui. Então, no momento, ele não está gerando a cena de seleção aleatória. Basta selecionar o primeiro na matriz. Então, precisamos de um pouco de código ou de uma função para escolher qual cena vamos realmente instanciar. Então, vamos ampliar, e eu vou dizer que var scene é uma cena lotada, e vamos querer selecionar spawn aleatório de uma lista de definições que podem ser distribuídas aleatoriamente . Então, vamos dizer definições aleatórias, exceto isso. E então precisamos criar essa função de seleção aleatória de geração Então eu vou fazer a função Control V para colá-lo. E então vamos dizer que as definições P são uma matriz de, vamos ver o que eles chamam de definição de geração. E vamos retornar uma única cena cheia. Então, se as definições de P estiverem vazias, podemos retornar null porque não há nada para selecionar Caso contrário, vamos calcular a partir de todos os pesos totais e gerar aleatoriamente um valor entre zero e o peso total para determinar qual cena estamos realmente Então isso é seleção aleatória, mas é seleção aleatória ponderada Então, digamos que se nosso peso total for flutuante, comece em 0,0 E então, para a definição ou as definições D e P, vamos pegar o peso total e aumentá-lo pelo peso da definição. Está bem? Então, fazemos isso para cada definição. Agora temos o peso total e precisamos gerar um valor entre zero e o peso total. Até agora, digamos que o valor aleatório seja um valor flutuante. E vamos pegar um F aleatório . Então, isso é zero a um ponto, tudo incluído, incluindo decimal, e será vezes o peso total Então, isso nos dará um valor aleatório entre zero e o peso total. E então digamos que o fluxo de peso verificado em V seja 0,0. Então, esse é o valor de peso que tentamos passar antes de atingir o valor aleatório Quando atingirmos o valor aleatório, retornaremos qualquer cena ou definição em que estejamos atualmente Então, para definição nas definições P, vamos dizer que o peso verificado mais é igual ao peso do ponto de definição E se o peso verificado estiver acima do valor aleatório , retornaremos a cena. Então, retorne o ponto de definição CM. OK. E então, se chegarmos ao fim e ainda não tivermos atingido nada, isso é um problema, então podemos enviar um erro. Ok, então aqui estou inserindo um erro. Não foi possível encontrar uma definição em porcentagens do valor de peso, em que o peso total verificado era porcentagens que o peso total verificado era E então eu estou substituindo essas porcentagens valor aleatório e pelo peso verificado Então, isso meio que mostra o que estávamos verificando, onde chegamos, e indica que na verdade não encontramos um verificado que estivesse acima do valor aleatório, que sempre deve acontecer porque o valor aleatório só pode ir até o peso total. Portanto, isso não deve ocorrer, mas se isso acontecer, temos uma mensagem de erro. E então, no final , podemos simplesmente dizer return null porque ele não foi capaz de encontrar uma definição adequada Então, isso faz mais sentido. Provavelmente quebrará algo imediatamente indicando que algo precisa ser corrigido na matemática nessa função. Mais uma vez, quero enfatizar que isso nunca deveria acontecer. Se nossa matemática estiver correta. Ok, então selecionamos o spawn aleatório da nossa lista de definições, e isso lida com o peso e os cálculos aleatórios Então, se eu rodar o jogo agora do jeito que as coisas estão, deveríamos ter metade dos esqueletos dos orcs Mas vamos ver. Pegamos os dois? Porque devemos pegar os dois. Então, temos alguns orcs surgindo. Ok, então, na verdade, o código estava funcionando perfeitamente bem para selecionar um spawn aleatório Eu só esqueci de usar a cena. Então, queremos ver a cena aqui. E em vez de instanciar zero de definição aleatória, nós apenas enviamos instanciate nós apenas enviamos Ok, agora podemos voltar ao spawn aleatório e remover a mensagem de depuração do Prince Está bem? E se jogarmos , deve funcionar bem. Na verdade, ele deve usar o que selecionamos aleatoriamente, em vez sempre o primeiro na matriz Portanto, devemos ter metade dos esqueletos dos orcs, mas aí está o nosso E com o passar do tempo, você verá muito mais orcs do que esqueletos por causa da espera. Ok, então isso é bom. E essa é basicamente a ideia. Ok, então a última coisa nesta parte que talvez você queira adiar quanto tempo até que uma definição de inimigo possa realmente aparecer no jogo Por exemplo, no início, talvez você só tenha orcs, mas depois de um tempo, você pode adicionar esqueletos Então, já temos o tempo decorrido. Então, se dissermos um tempo inicial e final em termos de tempo decorrido em que uma definição pode ser gerada, podemos controlar quando os orcs podem desovar e quando os esqueletos podem aparecer Então, se eu entrar na definição de spawning, podemos adicionar uma var de exportação aqui ou no horário de início um float, e isso pode ser 0,0 E então, o horário de término também será padronizado como 0,0. Então, o que queremos fazer com esses dois é começar a criar como um método que pode ser gerado Então, poderíamos dizer que a função pode ser gerada, o que, obviamente, retornará um verdadeiro falso booleano E para isso, na verdade, queremos passar o tempo decorrido porque isso faz parte da condição disso, temos que verificar a hora do jogo ou a hora em que o sistema de geração foi realmente criado E então usaremos isso para verificar se o tempo decorrido está dentro da hora de início ou da hora de término Portanto, se o tempo decorrido de P for anterior ao tempo inicial, retornaremos false Se a hora de término não for igual a 0,0, ou melhor, se a hora de término for maior que 0,0, acho que é um pouco mais fácil de ler. Em seguida, queremos verificar se o horário final realmente foi ultrapassado. Então, se a hora final for zero, estamos simplesmente ignorando. Então, e o tempo decorrido P estiver acima do tempo final , retornaremos false Caso contrário, passamos por todas as condições para que possamos retornar verdadeiras. Então, isso é basicamente tudo o que precisamos fazer para um gerador baseado no tempo, e apenas verificamos se ele pode ser gerado e apenas verificamos se ele pode ser E se não puder ser gerado, nós o removemos da lista que consideramos para seleção aleatória Você faria algo muito parecido. Se você também quiser, digamos, ter um número máximo para que eles possam ser gerados, basta passar o número que foi gerado e verificar se ele está acima ou igual ao número máximo que a definição de desova permitiria foi gerado e verificar se ele está acima ou igual ao número máximo que a definição de desova Isso seria útil para algo como um chefe que só pode aparecer uma vez Então você pode verificar: Oh, ele pode aparecer uma vez. Quantas vezes ele aparece? É um ou maior do que não gerá-lo. Vamos ver se voltaremos a isso, mas isso deve ser tudo o que precisamos para escrever agora. Então, agora, de volta ao sistema spawner, queremos basicamente filtrar spawnb a partir das Então, vou criar um filtro de função spawnb que usará uma matriz de definições de P definições, e essa é a arma. Essa é a definição de desova. E então retornaremos nossas definições filtradas. Portanto, retorne uma matriz de definição de desova. Então, criamos nossa lista filtrada aqui. Var filtrou uma matriz de definições de geração, e isso será igual a uma E então, para as definições de DF e P, verificaremos se o DEF pode ser gerado Acho que precisamos do tempo decorrido aqui, mas isso é uma variável local Então, podemos simplesmente passá-lo diretamente para isso. Então, o tempo decorrido, por exemplo, não precisamos colocá-lo como parâmetro para essa função porque faz parte do estado do objeto, que é o sistema de geração Então, se ele puder ser gerado, nós o adicionaremos à lista filtrada Portanto, definição de caneta de pontos filtrada. E então, no final, retornamos filtrado, então aqui em um intervalo aleatório, fazemos var spanable e isso será igual a filter spanable, que usará nossas definições aleatórias como parâmetro E então, em vez de selecionar a geração aleatória partir de definições aleatórias, selecionamos a geração aleatória da nossa variável filtrada que pode nossa variável filtrada Ok, agora que isso nos dá a habilidade no sistema de geração, se examinarmos as definições de desova, podemos dizer hora de início, hora Digamos que os orcs estejam sempre ativos. Mas então, para a desova de esqueletos, não podemos gerar esqueletos até 15 segundos, mas quando conseguimos gerar esqueletos, temos um peso de dois, então acabamos vendo muitos esqueletos assim que eles Então podemos jogar. E se toda a matemática estiver correta, inicialmente não veremos nada além de orcs Mas depois de 15 segundos, pode ser útil ter um horário para terminar o jogo ou algo assim, veremos se precisamos disso. Depois de 15 segundos, podemos ver que os esqueletos começarão a desovar porque agora podem ser expandidos agora podem ser porque o tempo inicial de 15 Ok, agora você pode ver os esqueletos começarem a entrar. Então, temos nossa segunda onda de inimigos e poderíamos simplesmente tornar os esqueletos mais resistentes Portanto, a dificuldade avança à medida que o jogo avança, porque adicionamos inimigos mais difíceis E, claro, no sistema de desova, aumentamos a taxa de desova também, Então você pode ver como isso funcionaria. Essa é a natureza de basicamente controlar a desova aleatória do nosso sistema de desova Isso é a maior parte do que realmente precisamos aqui. Bom trabalho acompanhando tudo até agora. Ok, então podemos fazer alguns ajustes aqui e ali mais tarde, se precisarmos, mas na maioria das vezes, esse é o nosso sistema gerador. Então, agora devemos começar a trabalhar aprimorar um pouco mais o combate e fazer com que nossos inimigos realmente sejam capazes de prejudicar nossos jogadores Seria um bom próximo vídeo. Então, vamos partir daí. 26. Configuração de Hurtbox para jogadores P25 e Hitbox do inimigo: Parte de nossa mecânica básica de combate será configurar a habilidade dos inimigos atingirem nosso jogador, o que envolverá a criação uma caixa de acerto para os inimigos quando eles se depararem com o jogador, e precisamos garantir que o jogador também tenha uma caixa de Hurt E provavelmente adicionaremos um tempo de invencibilidade apenas para garantir que não recebamos muitos golpes quando formos atacados por um inimigo desse tipo Ok, então em nosso player, criaremos nossos nós Hurt Box. Então, vou clicar com o botão direito do mouse na rota do jogador, adicionar um nó secundário e procurar o HRT Box two D. Enter, adicione-o Vamos atribuir o controlador de estatísticas, que ainda não adicionamos ao nosso player, para possamos clicar com o botão direito do mouse no jogador, adicionar um nó filho, um controlador de estatísticas Ok. E então queremos fazer algumas tarefas. Então, o objeto do controlador SAT será a raiz do jogador. E então, na caixa HRT, queremos atribuir o controlador estatístico Portanto, nossa caixa HRT, você pode ver pelo sinal de aviso, também precisamos de uma forma de colisão Então, vamos clicar com o botão direito do mouse nele e atribuir a ele um nó filho. Colisão em forma dois D. E , em seguida, no canto superior direito, faremos isso provavelmente em forma de círculo Ok, então temos essa forma de círculo aparecendo. Queremos reduzir isso até o tamanho em que queremos causar danos aos nossos jogadores Então, dependendo de como queremos fazer isso, podemos torná-lo um pouco menor ou um pouco maior do que nossa forma de colisão Vou crescer por enquanto, e depois podemos reduzi-lo, se necessário equilibrar o jogo ou para melhorar a sensação das coisas Então, isso já nos dá a capacidade de causar danos ao jogador. Agora precisamos dar aos inimigos a habilidade de causar dano ao jogador. Então, em nossa cena orc, vamos clicar com o botão direito do mouse em Orc, adicionar um nó secundário e clicar na caixa dois D. E então isso vai precisar de uma forma de colisão. Então, clique com o botão direito, adicione um nó secundário, forma de colisão dois D, e então, no canto superior direito, vamos transformá-lo em um círculo e, em seguida, reduzi-lo até onde queremos que o orc seja capaz Então, vou torná-lo um pouco maior do que a forma de colisão principal da colisão real Então, em nosso RT Box two D, se verificarmos o script, podemos ver que obtemos o sinal de acerto da caixa de acerto atingindo uma caixa RT Então, para causar dano, na verdade precisamos de outro script para causar dano no sinal atingido e emitido Antes disso, porém, vamos adicionar as camadas de colisão para nossa caixa de acerto e nossas caixas feridas Então, a caixa de acerto dois D na camada de colisão vai mascarar a camada do jogador Então, máscara da camada dois porque essa é a camada do jogador. Para as camadas em que essa caixa de quadril existe, podemos simplesmente desativar a camada um ou definir a camada três para o inimigo, se quisermos. Mas provavelmente vou desligar o monitorável porque essa é uma caixa de quadril unidirecional Ele só precisa detectar. Se encontrar uma caixa no quadril, ela não precisa ser monitorada por outros nós dentro do jogo, pelo menos atualmente Então, vamos jogar e eu vou fazer o inverso para o Box two D. Aqui, vamos desligar o monitoramento e vamos enfrentar a colisão Vamos criar a camada como jogador. Essa é uma camada dois muito importante aqui, podemos desligar a máscara. Então, dentro daqui, vou clicar com o botão direito do mouse em Hit Box two D e vou adicionar um novo nó, adicionar nó filho. Este será um nó dois D. E vamos renomeá-lo para algo como ataque de colisão. Então, quando o orc colide com outro inimigo usando essa caixa dois D, ele causará todo o dano como dano de colisão Muitos jogos clássicos têm esse tipo de coisa que um inimigo simplesmente corre até você e você sofre danos. Então, teremos que clicar com o botão direito aqui e criar um novo script. Então, vamos colocar o ataque de colisão nos inimigos. Eu acho que isso é apropriado. Crie. Vou renomeá-lo ataque de colisão de nome de classe aqui na parte superior Vamos exportar uma referência para a caixa de acerto Então Hit Box é do tipo Hit Box two D. E, em seguida, quando pronto, função em pontuação pronta, retorna void Vamos pegar o Hit Box e vamos nos conectar ao sinal de sucesso. Então, ponto é atingido, ponto se conecta, e nós vamos conectar ao bater. Então, agora precisamos, digamos, do dano at export var aqui, que será um número inteiro Podemos padronizá-lo para dez. Então, vamos obter o retorno de chamada para o hit com a função on hit underscore on Agora você precisa clicar com o botão direito do mouse em Hit e verificar os parâmetros do sinal. Então, temos a caixa Hurt dois D aqui. Ok, então isso também nos dará acesso às estatísticas. Então, dentro do ataque de colisão, vamos recuar. Então, temos a caixa P Hurt, que é do tipo Hurt Box dois D. Isso retornará vazio e, em seguida, atingiremos o jogador Ok, então ao apertar P Hurt Box two D, queremos pegar a caixa P HRT, e queremos causar dano tridal nela, e vamos transmitir o E aí está mais ou menos isso, porque já escrevemos isso na caixa de feridas. Portanto, a caixa Hurt já lida com relatórios. Eu já manipulo a configuração do HP, que emitirá o sinal para que o HP mude, se precisarmos disso E ele faz o cálculo. Também faz a proteção para garantir que possamos atingir o alvo Então, faz sentido usarmos essa lógica onde. Enquanto tivermos um ataque de colisão, colocamos a caixa de ataque aqui e ajustamos nosso dano Podemos ver se isso vai funcionar. Então, vou tentar encontrar um inimigo e ver se nosso jogador sofre o dano acima dele. Ok. Eu só preciso ter certeza de que Oh, ok, sim. Lá vamos nós. Nosso jogador foi atingido por dez. Sabemos que é o jogador e não o inimigo porque a lança atualmente faz 100 Agora, atualmente, parece haver um problema, que é que o inimigo que já está morto parece ainda ser capaz de atingir o jogador. Já demorou 100. Eu fui para o Death State, e o ataque de colisão ainda estava habilitado Então, poderíamos lidar com isso de algumas maneiras. Uma seria verificar o controlador de estatísticas e garantir que o controlador pilha do orc, o HP, esteja acima de zero ou que o orc ainda esteja Caso contrário, simplesmente ignoraremos completamente esse ataque. Essa seria uma maneira decente. Outra forma seria colocá-lo no estado de morte e depois desativarmos todas as caixas de acerto assim que nosso orc for considerado morto Acho que talvez seja muita responsabilidade pelo estado de morte. Então eu acho que pertence um pouco melhor aqui no ataque de colisão Então, o que faremos é exportar uma referência para nosso controlador de estatísticas, exportar V stats stat Então, o que vamos dizer sobre isso é que, se não for stats dot Live, voltaremos. Caso contrário, causaremos danos. Então, basicamente, enquanto o personagem não está vivo, ele não pode atacar, mas se estiver vivo, consideraremos o dano de colisão válido se conseguirmos essa conexão Então, agora, se voltarmos a jogar aqui, poderemos caminhar até um inimigo que acabou de ser derrotado sem sofrer danos. Ok, então eu preciso cronometrar isso corretamente. Ok, eu me deparo com ele e vemos que acertamos, mas esqueci de definir as estatísticas Portanto, pode ser um bom momento para uma afirmação. Então, afirme as estatísticas. Portanto, a estatística precisa ser definida para que possamos verificar se o personagem está vivo. E então, isso basicamente já exigirá que tenhamos o erro de refrigerante na caixa de sucesso, se esquecermos de colocá-lo no inspetor Ok, então aí perto. Clique em Ataque de colisão. Vamos atribuir as estatísticas. Vamos entrar em jogo. Vamos fazer isso mais uma vez. Encontre um orc E você pode ver que não sofremos danos se o orc já tiver sido derrotado, mais uma vez Sim, parece estar funcionando muito bem. 27. Cronômetro de invencibilidade de jogador P26 e definições de estatísticas personalizadas: Ok, então a última coisa neste vídeo que queremos configurar um período de vulnerabilidade, especificamente para o nosso player. Então, no Stat Controller, podemos entrar aqui. Portanto, no controlador SC, podemos criar um temporizador de invulnerabilidade Então, digamos que aqui embaixo V Invincible time e podemos padronizar isso para 0,0 Será do tipo flutuador. Portanto, é o momento em que o objeto não pode ser danificado após ser atingido . Ok, então com nosso tempo invencível padronizado para zero, isso vai ser bom para No entanto, para um jogador de quatro horas, queremos ter nosso valor personalizado para o tempo de Invincible. E provavelmente também queremos personalizar coisas como HP, velocidade, HP máximo, etc Então, estamos realmente chegando ao ponto em que precisamos configurar algum tipo de definição de estatísticas, onde podemos definir quais serão as estatísticas iniciais de cada personagem. Então, se pudéssemos criar um novo script para isso, que se pareceria muito com nossa definição de armas, em que estamos apenas definindo propriedades sobre o personagem e seu bloco de estatísticas Então, na foto do personagem, tudo bem, clique em Criar um novo script, e vamos chamá-lo de definição de sublinhado estatístico Isso se estenderá do recurso e clique em Criar, ok? Em seguida, pesquise o script que acabamos criar a definição Stat, clique duas vezes nele E chegaremos até aqui até o topo. Então, definição estatística do nome da classe. Portanto, isso definirá as estatísticas padrão para um tipo de objeto. Então, as estatísticas que queremos vão basicamente espelhar o que temos no controlador de estatísticas Então, vamos entrar no controlador de estatísticas e, por enquanto, vou copiá-los para nossa definição de estatísticas Vou remover todo esse código setter. Porque queremos apenas definir propriedades editáveis de exportação que basicamente não executam nenhum código extra São apenas dados puros que são salvos essencialmente no GIDOEditor Portanto, não precisamos estar vivos e queremos um padrão para o HP, o FenciBT HP e o MAX HP Então, vamos exportar tudo isso na exportação para MaxHP na exportação para HP Por aqui, vamos exportar por velocidade e exportar por tempo de invencibilidade Talvez você também queira fazer alguns comentários a eles. Portanto, MaxHP, integridade máxima para o objeto, HP, integridade inicial para o objeto atual Ok, e isso será isso. Então, agora precisamos de uma maneira de nossa definição de estatística ser carregada no controlador de estatísticas Você pode colocar uma função de carregamento na definição de estatísticas, o que transforma o recurso em um pouco mais do que apenas dados de pares Bem, poderíamos colocá-lo no controlador de estatísticas e em algum tipo de método de estatísticas inicializado onde ele conhece o tipo de definição de estatísticas e, em seguida, ele pode carregar todos os valores de um objeto desse Então, eu vou fazer isso dessa maneira. E isso significa que precisaremos criar uma nova função aqui na parte inferior. Como o controlador de estatísticas precisará chamar initialize na definição de estatísticas de qualquer maneira, porque esse é o nó que o nó manipulará quando estiver pronto para se configurar Então, de qualquer forma, haveria uma pequena dependência da definição de estatísticas Então, vou criar a função, configurar estatísticas, e isso vai usar uma definição P, que é uma definição de estatística Bem, retorne o tipo void e deixe-me adicionar algumas linhas aqui. Então, nas estatísticas de configuração, vamos apenas espelhar a definição nesse nó. O HP máximo será igual à definição p mxHP. HP será igual ao ponto de definição p HP. Vamos ver o que mais a velocidade será igual à velocidade do ponto de definição p, e o tempo invencível será igual ao ponto de definição P Invincible T. Então, agora precisamos fazer isso quando estiver ponto de definição P Invincible T. Então, agora precisamos fazer isso Então, em tempo invencível, adicionaremos o sublinhado da função pronto e diremos que configuraremos estatísticas com Então, precisamos exportar uma definição no nó para que possamos realmente fazer isso. Então, no topo, vamos fazer Export VR Stat seja uma definição de estatística de tipo Ok. E então usamos isso assim que estivermos prontos. Portanto, configure estatísticas com a definição de estatísticas. Isso carregará todas as estatísticas em nosso valor de tempo de execução. E isso nos permite personalizar os valores das estatísticas básicas de nossos personagens usando algo que podemos configurar no editor. Então, se clicarmos no controlador Stat, vamos para o canto superior direito Posso criar uma nova definição de estatística aqui para o nosso Oc. E digamos que o Mx HP deva ser 40 e 40, e a velocidade seja 25 Então, salvamos isso agora na pasta onde temos os orcs. Clique na definição de estatísticas, salve como, e podemos colocá-la na pasta do inimigo Então, Ok Stats. Parece um nome perfeito lá. Salve isso. Ok, e essa é a definição do Ok Stat. Então, quando carregar, ele será carregado com esses valores assim que o personagem estiver pronto. Ok, então isso é basicamente isso para o orc. Agora, eu também quero copiar essa configuração de hit box para o esqueleto Então eu vou para o Controle C, vou até o esqueleto, Controle V, e colo Talvez eu sofra um ataque de colisão e só vou aumentar o dano para, digamos, 25 Vamos atribuir as estatísticas ao controlador de estatísticas, e a forma da colisão sendo a mesma funciona bem Usa as mesmas camadas de colisão. É uma pedra em mim tentar acertar o jogador. Então, todo o resto está configurado e está tudo bem. E então precisamos configurar o controlador de estatísticas. Então, inicie o controlador aqui, vá para o topo ou para a direita. E crie uma nova definição de estatística. Digamos que o esqueleto tenha mais de 50 pontos de vida, 50 de vida, uma velocidade de 40 está bem Então, clicaremos com o botão direito do mouse em Salvar como e diremos que as estatísticas do esqueleto pontuam TRS, Agora precisamos fazer isso para o jogador. Vá até o player, clique no controlador de estatísticas, vá para o canto superior direito, faça uma nova definição de estatísticas Agora, aqui eu nos quero na hora invencível. Digamos que um personagem seja invencível por 0,2 segundos após ser Daremos ao personagem uma velocidade base de, digamos, 100 e o HP máximo tem 100. Acho que vou deixar isso como o começo. Então, clique com o botão direito na definição de estatísticas. Salve como e nós o salvaremos na pasta Player. Playerstt dot TRS, clique em Salvar. E agora, cada personagem deve ter estatísticas diferentes. A última coisa que precisamos fazer é realmente usar o cronômetro de invencibilidade Então, no St Controller, precisamos acionar Invincible com uma chamada de método Então, vamos criar um conjunto de funções Invincible aqui, que retornará o tipo void E então teremos uma variável local para saber se é invencível ou não Portanto, a variável invencível é um booleano. O padrão será falso. Se for verdade, o objeto não pode sofrer danos. Ok, então para que possa ser atingido, queremos dizer que o personagem está vivo e não invencível Então, estou usando isso com as palavras-chave em vez do símbolo lógico. Eu acho que isso torna um pouco mais fácil de ler, em certo sentido. Portanto, se o personagem estiver vivo e não for invencível, ele poderá ser atingido E queremos que invencível seja igual a verdadeiro, mas também queremos iniciar um cronômetro aqui E diremos que isso é igual a um novo cronômetro, é igual a um ponto novo do cronômetro. E então adicionamos isso como filho a esse objeto, temporizador de invencibilidade, e nos conectaremos ao Então, invincibility timer dot timeout dot connect on Invincible Timeout . Então, controle, veja isso e cole aqui. Função no tempo limite de invencibilidade. Essa abertura e o vazio. E diremos que invencível é igual a falso. Ok, agora precisamos iniciar o cronômetro. Hora da invencibilidade ou início, e diremos que a hora é a hora invencível Isso deve lidar com a lógica de saber se podemos ou não bater porque o personagem é invencível ou Ok, então para definir invencível, podemos verificar quando o HP está configurado e, se o HP cair , queremos acionar a Mas acho que o que pode deixar nossa intenção clara é criar também uma função de sofrer danos nessa definição Então, poderíamos fazer algo como funcionar, sofrer dano e passar um dano de P para aqui. Nós marcamos e anulamos, e isso vai pegar HP e configurá-lo para P de dano E então queremos definir o personagem como invencível. Poderíamos até dizer que se o tempo invencível for maior que 0,0, definiremos Sobre esse objeto. E o HP , na verdade, será menos igual ao dano aqui, porque queremos pegar seu valor atual e atualizá-lo Então, isso ainda vai dizer que o live igual a HP é maior que zero Se você quiser, você pode até mesmo fazer get live apenas uma função que verifica isso, o que também seria bom, em vez de fazer a configuração anterior. Mas nós já tínhamos isso. Funciona bem. Nós vamos continuar com isso. Então, agora, sempre que causamos dano, realmente queremos chamar take damage no controlador de pilha Então, vamos descobrir onde estamos causando dano, como se fosse o projétil Ok, então aqui podemos ver que tudo volta para a caixa Rt. Então, vamos clicar com o botão direito do mouse e entrar nisso. E em vez de configurar o HP diretamente, diremos que o controlador de estatísticas não sofre danos e transferimos o dano P. Então, podemos cortar essa linha e, na verdade, não precisamos calcular isso porque esse cálculo é feito automaticamente no controlador de estatísticas Então, isso ilustra mais ou menos nosso argumento de que, se nosso controlador de estatísticas sofrer danos, ele pode estar fazendo outras coisas, como colocar invencível no personagem porque nosso personagem sofreu porque nosso Não é só porque mudamos o valor da HP. É especificamente porque recebemos danos de uma fonte danificada. Ok, então vamos clicar em Play e ver se tudo se encaixa. Teremos que sofrer danos de alguns inimigos e, em seguida, queremos ter certeza que só podemos sofrer danos uma vez a cada quarto de segundo. Então, se eu atirar aqui, precisamos de mais alguns inimigos para que isso funcione. Pode ser até mais fácil se eu desativar os projéteis. Ok, então eu vou encontrar esses caras. Eu só deveria ver os danos ocorrerem uma vez. Ok, 25. Acho que está funcionando. Se eu passar por tudo isso. Só estou vendo danos surgirem uma vez de cada vez. Para o VLC, com certeza, porém, preciso desligar o projétil Então, vou deletar temporariamente a arma de lança da cena aqui. Você não precisa fazer isso. Só estou demonstrando. Ok, então eu vou caminhar até os inimigos. Ok, então só somos danificados uma vez. Agora, essa colisão só ocorre entrar na área Então, se ficarmos em cima do inimigo, ainda seremos atingidos apenas uma vez. Está bem? Você pode ver que, embora haja um monte de caras batendo em nós, só somos atingidos uma vez cada quarto de segundo, mais ou menos, desse jeito E nossos personagens já estão prontos, então não podemos ser mais atingidos. 28. Parte 27 Implementando dano periódico para Hitboxes inimigos: Corrija o problema em que a caixa HIP só pode danificar uma vez após outra área. O HipXTD entra nessa caixa de acerto, mas não quando persiste dentro dela. Podemos ajustar um cronômetro dentro da caixa do quadril para D para verificar se a caixa do quadril ainda está dentro da área, e então podemos continuar causando danos a ela periodicamente Ok, então, uma vez emitido o hit, eu também posso adicioná-lo às áreas do trato e ao script Então, digamos que var targets, que será uma matriz de Hurt box two D, que atualmente não é nada. E diremos que depois de acertar, acrescentamos os alvos, a área P. Ok, agora precisamos nos conectar ao sinal esquerdo da área. Então, a área saiu do dot connect. E vamos usar o retorno de chamada na área saída. Ok. Então, funcione na área saída. Nós obtemos a área P. Então, queremos verificar se é uma caixa HIT dois D. Então as áreas do tipo área dois D. Ok, então verificamos se a área P é Hurt caixa dois D, então vamos continuar. Agora vamos verificar se o ponto do alvo tem área P e, em seguida, vamos apagá-lo dos alvos Os alvos apagam a área do IP. Ok, agora os alvos só existirão enquanto a caixa Hurt do alvo persistir dentro da área da nossa caixa de acerto Podemos verificar a cada momento se precisamos danificar o inimigo novamente. Ok, então poderíamos fazer isso com algo como, digamos que temos um cronômetro opcional, então em Export var timer timer, e então nos conectaremos ao sinal de tempo ou tempo Então, timer dot timeout dot Knect e diremos Ok, então vamos colocar essa chamada de volta aqui, funcionar na hora certa ou TO. Isso retornará vazio e tentaremos atingir essa área. Portanto, no tempo ou tempo limite do Target e dos alvos atingimos um ponto em Mt Target Portanto, se os objetos ainda estiverem na área depois de terem feito o golpe inicial, depois de cada vez ou período, eles serão atingidos novamente. Então vamos para Ok e vamos dar uma olhada na nossa caixa de acerto dois D. Ok, e talvez queiramos ser um pouco mais claros sobre para que serve esse cronômetro Então, digamos que isso seja na verdade um cronômetro de danos, e eu atualizarei a propriedade quando estiver pronta Ok, agora, para nosso cronômetro de danos, queremos clicar com o botão direito do mouse no hipbox two D e adicionar um E diremos que, para isso, fazemos cerca de 0,25 segundos. Isso será autosrt, e então só precisamos referenciá-lo no Hip Box two D. Vou renomeá-lo para temporizador de danos para que os nomes também coincidam Então clique em Hit Box two. Atribua o cronômetro danificado. Agora isso vai se conectar ao sinal dentro do script. E para cada objeto ou alvo que estiver na área quando o cronômetro expirar, ele acionará isso E como essa não é uma única foto, ela se repetirá automaticamente. Então, a cada 0,25 segundos, ele continuará fazendo isso e verificará os alvos todas as vezes Então isso provavelmente é bom lá. Só precisamos que o esqueleto tenha a mesma coisa Vou controlar a cópia C desse cronômetro para o esqueleto E vamos colar o Control V no Hip box two D. Vamos atribuí-lo no Hit box dois D e no canto superior direito, atribuir o cronômetro danificado, salvar e executar Ok, e podemos ver que em algumas caixas do quadril dois Ds especificamente como o projétil, o projétil de velocidade, não têm isso Portanto, precisamos deixar claro que dizemos: Se o cronômetro estiver danificado, nos conectamos ao sinal Portanto, isso é opcional, e eu escrevi um comentário lá para deixar claro que o cronômetro opcional emite periodicamente sinais de acerto nos alvos dentro da área da caixa do quadril, duas vezes após um determinado tempo Ok, vamos correr novamente. E vamos ver se um orc pode realmente nos causar dano duas vezes Bem, isso vai ser um pouco difícil com as lanças lá Vamos desativar a lança também. Portanto, desative a arma de lança ou remova-a temporariamente. Vamos voltar para a cena. Ok, e vamos encontrar um orc para nos prejudicar algumas vezes. Ok, então aqui temos nosso k. Vamos ver quantas vezes podemos sofrer danos. Sim, definitivamente podemos ser atingidos várias vezes pelo mesmo orc E isso provavelmente é muito rápido, honestamente. Então, vamos juntar isso. Primeiro, vou controlar Z para adicionar a arma de lança novamente Vamos até o orc e eu vou definir seu tempo de peso para 0,5 segundos. E se parecer que o jogador sofre muito dano quando vários inimigos se agrupam sobre ele, você ainda pode aumentar o cronômetro de invencibilidade, para que o número máximo de acertos por segundo caia de 5 a 4, dependendo se você atingir o cronômetro de 0,2 ou 0,25 muito dano quando vários inimigos se agrupam sobre ele, você ainda pode aumentar o cronômetro de invencibilidade, para que o número máximo de acertos por segundo caia de 5 a 4, dependendo se você atingir o cronômetro de 0,2 ou 0,25 segundos. No entanto, você deseja ajustar 29. Derrota de jogadores no P28: personagem fica sem HP, precisamos mudar para o estado de morte, e parte disso também impedirá que os ataques continuem E, eventualmente, colocaremos um game over na tela, mas vamos fazer com que chegue ao fim do estado de morte por enquanto. Então, na cena do jogador, temos nosso estado de movimento. Queremos entrar em um estado de morte, e acho que podemos, na verdade , entrar no cenário organizacional e até mesmo copiar e reutilizar isso Se eu examinar o roteiro do estado de morte, não vejo nada sobre ele que realmente seja um problema, exceto talvez o trimestre aqui no final. Talvez queiramos apenas notificar um sistema de jogo de que o personagem foi derrotado. Então, vou apenas copiar o roteiro. Vamos até o jogador. Vou clicar aqui e adicionar um novo nó de estado do Limbo Digamos que o jogador derrotou o estado. Então, jogador derrotado, clique com o botão direito do mouse, anexe um script e, em seguida, o criaremos na pasta do jogador. Vou colar isso. Vamos renomear o nome da classe aqui para o estado de jogador derrotado Ok, vamos verificar o nome da animação e garantir que ela esteja no player de animação. Então, a morte do jogador de animação, nós temos isso aí. Ok, então está tudo bem. Se entrarmos no estado de morte, então vamos querer adicionar uma faixa chamada Method Track ao nosso estado de jogador derrotado. E se formos até o final aqui, vamos habilitar o encaixe no canto inferior direito também, se isso ajudar Então, ajuste para 0,6 e, em seguida, clique com o botão direito do mouse e classifique uma chave, e chamaremos de concluído no script Ok, então estou tentado a usar o sistema de combate já existente e depois fazer algo como denunciar a derrota do jogador A derrota do jogador é mais uma de reiniciar o jogo ou anunciar o fim do jogo Portanto, não é realmente uma função do sistema de combate. Então, para separar as preocupações, posso, na verdade, criar um novo nó para lidar com o gerenciamento de jogos, e isso também pode incluir salvar e carregar. Vamos ver. Então, se formos até a raiz do nosso projeto e sistemas, eu gostaria de criá-los aqui. Vou clicar com o botão direito do mouse e criar um novo script, digamos , que chamaremos de gerenciador de jogos dot gD. Acho que isso funciona como um nome. OK. E no gerenciador de jogos, vamos deixá-lo como um nó porque vamos torná-lo um Singleton de carregamento automático Por que não usamos um relatório de funções no final do jogo, para que ele possa ser chamado de qualquer lugar, desde que façamos referência ao gerente do jogo. E quando denunciarmos o fim do jogo, vamos apenas imprimir, que imprimirá sequências de caracteres no console, e diremos que o jogador foi derrotado no fim do jogo Posteriormente, substituiríamos isso pela interface de usuário para que pudéssemos realmente mudar para um novo jogo ou ver as estatísticas do fim do jogo, etc Mas isso pelo menos mostrará que está funcionando. Ok, então queremos pegar o gerente do jogo e criar uma cena para que possamos editar as variáveis de exportação se precisarmos delas. Então eu vou escrever clicando em Sistemas, criar uma nova cena. Este será o gerenciador de jogos dot TSCn. Vou clicar com o botão direito do mouse aqui, alterar o tipo de nó para um nó. Vamos arrastar o script do gerenciador de jogos para ele. OK. E então queremos salvá-lo, vá para Configurações do projeto. Dentro do Globals, queremos carregar automaticamente o anúncio dot TCN do gerenciador de jogos de sistemas, e agora ele é um símbolo de gerenciador de jogos referenciável globalmente referenciável Então, se quisermos usar isso, podemos simplesmente voltar para o estado do jogador derrotado e terminar. Em vez de ficarmos na fila livre, deixaremos o personagem lá. E vamos dizer que o gerente de jogo não reporta o fim do jogo, e isso é tudo o que precisamos fazer. Um motivo para não remover o jogador da cena é que, do jeito que as coisas estão agora, todos os inimigos dependem da existência do jogador para que ele possa continuar se movendo. Então, assim que você remover o jogador da cena, todos os scripts inimigos começarão a ser quebrados. Agora, se você quiser detalhar isso completamente e permitir que o personagem seja removido da cena do jogo, basta verificar basicamente cada sequência, digamos, da cena de perseguição aqui. Você só precisa se certificar de que o alvo ainda é válido e, se não for válido, basta retornar. Então, isso pode ser algo como se o alvo do sublinhado fosse igual a nulo, então você retorna, e isso significa que ele simplesmente não se move Então, você sabe, para nos divertir, poderíamos realmente ir até o jogador e no estado de jogador derrotado. Na verdade, podemos adicionar o agente dot q free e ver como isso funcionaria. Então, se eu adicionar essa verificação de que Targets Not null para a cena de perseguição, ela vai quebrar ou vai funcionar aqui? Então, vamos tentar. Vamos ver se nossos inimigos ainda conseguem continuar funcionando sem nenhum jogador na tela. Ok, então vamos ser derrotados. Na verdade, ainda não configurei a transição para o player HSM Então, no player HSM, vamos criar outra função, configurar as transições OK. Então, isso exigirá que adicionemos uma transição do estado de movimento para o estado derrotado, e isso acontecerá no evento derrotado. Ok, então vamos defini-los aqui para o jogador HSM no estado export var move, que é um estado de limbo no estado derrotado de export var, que é um estado de limbo E então criaremos uma constante para defeated, que será um nome de string igual a e aspas Ok, agora precisamos atualizar nossos nomes de variáveis aqui para adicionar a transição. Então, um invólucro de cobra para essas variáveis. E só devemos ser capazes de passar do movimento para derrotá-lo , na verdade, porque não temos nenhuma mecânica de ressurreição no Então, uma vez derrotados, os jogos terminam, e tudo ficará bem. Você sempre pode adicionar uma transição volta se tiver alguma forma de ressuscitar. Agora, queremos chamar as transições de configuração dentro do HSM de configuração, configurar as transições lá e podemos lidar com a transição conectando-nos ao sinal de estatísticas do player Então, depois de afirmar que os jogadores não são nulos, queremos nos conectar ao sinal no player Então esse realmente será o sinal no controlador de estatísticas Ele pode referenciar diretamente o controlador SAT ou conectar-se ao controlador de estatísticas por meio do player, embora ainda não tenha essa configuração Então, acho que, neste caso, seria um pouco mais direto apenas referenciar um extra em Exportar estatísticas de VR do controlador de estatísticas. Ok, e aqui embaixo diremos que stats Alive mudou dot Connect, e estará em Alive alterado Então, vamos criar essa função na parte inferior e retornar a chamada. E isso terá o valor P, o novo valor do live. O retorno S é nulo. Então, se o valor P for igual a falso, então queremos despachar o evento derrotado Ok, então isso resolverá o acionamento da transição do estado de movimento para o estado derrotado se estivermos no estado de movimento Se você acabar adicionando vários outros estados, também há a opção de fazer qualquer estado aqui. Então, isso fará com que, se os personagens forem derrotados, de qualquer estado, você possa simplesmente fazer transição diretamente para o estado derrotado. Na verdade, isso pode ser preferível pensar a longo prazo, porque talvez você adicione algum tipo de estado de ataque em que reproduza uma animação diferente Você ainda gostaria de poder passar imediatamente para derrotado em vez de simplesmente passar de movimento para derrotado quando esse despacho ocorrer Caso contrário, se você despachar quando o personagem não estiver no estado de movimento, talvez ele nunca vá para o estado de morte Então, acho que essa geralmente seria a maneira preferível de fazer isso Ok, agora precisamos atribuir tudo no inspetor Então, atribua o controlador de estatísticas, atribua o estado de movimento e atribua o derrotado 30. P29 Testando e Aprimorando o Comportamento na derrota de um Jogador: Para tornar isso mais rápido, vou clicar em Stats Controller Vamos pegar o HP e configurá-lo para dez, e eu aperto play. Então, se nosso personagem for atingido uma vez, mudaremos imediatamente para o estado de morte. Ok, então vamos encontrar um orc. Ok, vamos lá. Ok, então chegamos ao estado derrotado. Mas podemos ver que o agente não tem estatísticas porque não exigimos isso do personagem. Então, se quisermos apenas ser consistentes, então sim, podemos adicionar estatísticas ao jogador. Acho que não há problema em referenciar estatísticas por meio do jogador porque geralmente entendemos que o jogador terá estatísticas, especialmente em um tipo de jogo de RPG Além disso, podemos eliminar essa variável de velocidade aqui. Pode ver que o jogador ainda está usando a velocidade do script básico em vez da velocidade das estatísticas. Então, sim, vamos obter uma referência em Export var stats, que é um controlador de estatísticas OK. E então, quando temos velocidade, queremos usar estatísticas de velocidade por pontos. Está bem? E vamos copiar isso e substituí-lo lá embaixo também. Então, use-o de forma consistente em nosso processo físico para o jogador. Está bem? Se atribuirmos as estatísticas e o inspetor, podemos fazer isso ali mesmo E então, se olharmos para o HSM, não precisamos mais de uma referência direta às estatísticas porque já as temos por meio do player Assim, podemos alterar player.stats.ai e nos conectaremos à transmissão alterada por meio disso e nos conectaremos à Portanto, basta ser um pouco mais consistente sobre como fazemos as coisas em nossos scripts, embora ambas as opções, é claro, funcionem, seja diretamente no controlador de estatísticas ou por meio do player Então, vamos entrar no modo de jogo e fazer com que um personagem seja derrotado aqui. Então, os personagens foram removidos, e o que vai acontecer é que, quando novos personagens criarem novos NPCs, afirmamos que o jogador alvo precisa existir, mas ele não Ok, então, na verdade, vamos remover essa afirmação porque podemos personagem apareça no mundo do jogo e não ter um alvo Então, se for nulo, acho que ainda pode funcionar E então não haverá alvo porque o personagem já está morto. E então entramos aqui. Quando o alvo é nulo, não fazemos nada para o estado Chase. Então eu vou clicar em play. Ok, então tem isso. Os inimigos meio que param. Sim. Ok, então você pode ver que está tentando atribuir uma instância liberada anteriormente Então, o que precisamos aqui é de mais uma verificação. Diremos que I agent dot target dot player não é igual a null, então vamos atribuí-lo Ok, isso parece estar bom agora. Sem mais erros. Agora, os personagens ainda estão funcionando. Então, podemos até mesmo colocar os inimigos em um estado ocioso se quisermos que seja um pouco mais crível, porque eles terminaram seu trabalho, então agora eles estão apenas Então, o que realmente poderíamos fazer aqui no Update é enviar um evento Digamos que esse seja o evento ocioso. Ok, então vamos despachar o Idol do estado de Chase, Então, agora, se formos para o Ok Enemy HSM, queremos adicionar uma transição do estado Chase para um estado ocioso Então, digamos que adicione transição. Do estado de Chase ao estado ocioso. E isso será no evento Idle. Ok, então precisamos de um estado ocioso. Então eu vou fazer em Export var Idle state, que é um estado Limbo Vamos clicar com o botão direito do mouse em Adicionar em um novo estado Limbo do nó secundário. Ok, e isso vai ser muito parecido com o estado de morte. Vou entrar no Death State e copiar tudo aqui para o novo estado do limbo Então, esse será o estado ocioso aqui. Clique com o botão direito, anexe um script, Idol State. E vamos controlar a pasta V em apenas renomear esse estado inativo Se eu fosse criar mais estados, provavelmente começaria a pensar em criar um estado básico de animação neste momento. Mas, na verdade, não é muito código. Estamos duplicando aqui, então não é realmente um grande problema. E essa é a maneira mais simples de lidar com isso. Pelo menos falando a curto prazo. Ok, então com o AlpiPasted for the Idol state, eu só quero renomear a animação aqui para A animação já é reproduzida no Blackboard. Queremos parar com essa parte sobre fazer com que o agente não esteja mais vivo, porque isso não é verdade. Basicamente, é só isso. Temos uma animação. Recebemos a reprodução da animação no Blackboard e, quando entramos, reproduzimos a animação E a animação está ociosa aqui. Então, agora no Enemy HSM, queremos apenas atribuir o estado ocioso Além disso, isso deve lidar com a transição. Queremos fazer a transição para o estado de morte e mudar isso para qualquer estado. Então, quer os personagens estejam ociosos ou perseguindo, podemos fazer a transição para a morte se o evento da morte ocorrer. Isso é importante. E então só queremos ter certeza de que copiamos o estado ocioso para o esqueleto Cole-o aqui e atribua-o ao HSM inimigo. Portanto, atribua à direita, estado ocioso. Além disso, deve ser bom. Então, vou clicar em play e veremos se conseguimos derrotar nosso personagem. Ok, então vamos lá. Nosso personagem mudou para o ídolo e pronto Então, eles não precisam mais de um alvo. Eles não estão mais perseguindo um alvo. Eles estão apenas ociosos em seu estado ocioso. 31. L30 Criando uma cena Pickup2D: Agora vamos começar a criar captadores de EXP para que nosso jogador possa ganhar pontos de experiência e subir de nível Portanto, haverá algumas etapas envolvidas nisso. A primeira será criar nosso script básico de coleta, um script de coletor de coleta, um script de coletor de coleta, e depois garantir que nosso personagem possa realmente adquiri-los e, em seguida atribuir o aumento de XP à experiência atual do jogador Então, vamos começar criando a verdadeira pickup mundial do game two D. Então, vou criar uma nova nota aqui. Vamos usar duas cenas D, e eu vou renomeá-las para pegar duas D. Tudo bem, clique com o botão direito nela, e vamos mudar o tipo para ser uma base da Área dois D. E agora, se clicarmos no botão de script em anexo, obteremos uma captura dois D que estende a Área dois D. Digamos a pasta Objetos, e então eu vou criar uma nova pasta dentro Vamos chamá-lo de pickups. Então eu posso salvar o captador abaixo do quadrado dois pontos D GD dentro daqui, criar E na parte superior, vamos dar a ela o nome da classe pickup two D. Vamos salvar isso nas captações da pasta Objetos Pickup tdt TACN. Então guarde isso aí. Então, esse será um nó físico mundial que representa um objeto geral que pode ser captado e aplicado a um personagem de uma forma ou de outra. Então, isso pode significar aplicá-lo diretamente às estatísticas ou, em outras circunstâncias, pode significar que você o pega e adiciona ao inventário de um personagem. Não teremos um inventário para o jogo, mas poderemos adicionar níveis ao carregamento armas ou criar um novo carregamento de armas para um novo tipo de arma Para pegar dois D, queremos criar uma função T para que possamos tirar o objeto do mapa do jogo e aplicá-lo aos personagens Então, digamos que a função Tr take, que precisará de um alvo. Portanto, o alvo P não é dois D, e queremos retornar um booleano se isso foi bem-sucedido ou não Ok, então vou inserir um erro aqui que diz que é uma função virtual, implemente um script estendido. Agora, no Gudo 4.5, eles terão classes abstratas, que torna a configuração mais concreta, pois adicionam algumas palavras-chave extras para isso Mas como estamos no Gudo 4.4, que é a versão estável atual, faremos isso da maneira antiga, o que basicamente significa que precisamos lembrar que, quando estendemos nossa classe D pickup two, precisamos substituí-la manualmente por uma nova versão da função Com os mesmos parâmetros e tipo de retorno. Para TriTek, retornaremos false porque estamos tentando pegar um objeto nessa classe abstrata, que é o pickup two D. Então, para os diferentes captadores no mundo do jogo, queremos que todos tenham sua própria forma personalizada de se aplicar ao jogador ou nó se aplicar ao jogador ou Portanto, precisaremos implementar um script de extensão personalizado para cada um deles, L um para EXP e outro para coleta de armas, ou pode haver um captador ou pode haver um Então, todos eles funcionarão de forma um pouco diferente, então todos precisam de seu próprio método tritak Ok, então temos nosso script Pickup two D aqui. Vamos clicar com o botão direito do mouse e adicionar um nó secundário. Precisamos de uma forma de colisão. Então, para a forma de colisão aqui, vou até essa forma no canto superior direito e vamos transformá-la em um círculo Então, você provavelmente também deseja usar o sprite padrão aqui. Então, vou clicar com o botão direito aqui, adicionar um nó filho e queremos obter um sprite Então, para um objeto que vai reproduzir apenas uma animação repetidamente, sem trocar nem nada, acho que Sprite two D animado é a melhor opção Por exemplo, se uma moeda está girando no mapa repetidamente e você só quer que ela reproduza automaticamente aquela animação, então o Sprite two D animado é perfeito para Então, vamos selecionar isso e clicar em Criar. Agora, para os ícones do jogo, eles podem nem ser realmente uma animação. Mas se vamos fazer disso o modelo padrão, quero abrir isso como uma possibilidade. Então, para o nosso Sprite animado, vamos até a animação aqui Criaremos um novo recurso de molduras Sprite e o abriremos. Portanto, temos uma janela de animação diferente no canto inferior esquerdo. Então, eu poderia simplesmente renomear isso para Idol, se eu quiser. Vamos entrar na arte. Queremos ver os ícones do Raven Fantasy e a planilha completa do Sprite, vamos dar uma olhada nisso e ver se há algo que queremos Então, para acessar isso corretamente a partir desta janela de animação, há este ícone Ad frames da Sprite Sheet Então clique aqui. Em seguida, vá para Art fantasy icons, fall Sprite sheet, 16 por 16 Realmente, você poderia usar um maior, se quiser. Talvez eu use apenas o 32 por 32. Então, com um pouco mais de resolução, abra-a, basta selecionar os ícones desejados. Ok, agora, para que isso seja dividido corretamente, precisamos do número certo de linhas e colunas em nossa planilha de sprites Ou se você sabe o tamanho de cada ícone, acho que você pode simplesmente ir até o tamanho aqui e colocar 32 30 Sim. Ok, essa é definitivamente a maneira mais rápida de fazer. Quando você altera um, ele calcula automaticamente o outro. Então, temos 16 horizontais. Realmente, essas são as colunas e, em seguida, 128 verticais são as linhas. Então, em vez de calcular isso, sabemos que cada um tem 32 por 32. Está bem? Agora podemos facilmente escolher o ícone que queremos a partir disso. Então você pode usar o que quiser como EXP Gem, acho que no projeto de modelo, eu estava usando este aqui Então, meio que uma joia azul. Nós adicionamos esse único quadro. E isso seria reproduzido automaticamente se verificássemos a reprodução automática lá embaixo, mas você pode ver que isso nem precisa ser reproduzido E provavelmente terá um desempenho um pouco melhor se desativarmos a reprodução automática Então, está apenas mostrando esse quadro e não está tentando nem mesmo repetir nada. Pura suposição da minha parte, mas vamos colocar isso aí E esse será nosso pico padrão para o Pickup two D. Então, para o nó raiz do Pickup two D, provavelmente também queremos configurar as Então, acho que não temos uma camada específica para captadores. Então, vamos adicionar uma nova camada de colisão. Basta fazer a camada cinco e dizer captadores. Ok, perto. E então queremos, é claro, colocar o captador na camada cinco e desligar a máscara Vamos desligar o monitoramento porque isso será detectado por alguma coisa. Não é monitoramento de captações. Ele permite que o jogador que está pegando o objeto faça a detecção Então, isso é apenas monitorar uma tigela com a camada cinco. E essa é a cena base da nossa picape. 32. L31 Como implementar um sistema de captação de experiência com herança: O que podemos fazer no canto inferior esquerdo é procurar a coleta novamente. Isso deve mostrar a pasta de pickups, e queremos clicar com o botão direito do mouse em Pickup two D e fazer uma cena herdada Então, isso está no topo aqui, nova cena herdada, o que significa que estamos criando uma nova cena com base nessa cena, então ela herda todos os mesmos padrões Então, criamos essa nova cena, e você verá que alguns desses nós ficam laranja, o que significa que eles são na verdade, baseados na cena principal. Você pode entrar em contato com o pai clicando aqui. Assim, você pode ter cenas dentro de cenas. E queremos renomear o nó raiz para, digamos EXP pickup two D. Porque queremos ser específicos sobre o que estamos E vamos salvar isso como uma nova cena. Então XP pickup tod dot TCN, guarde isso. E então vamos clicar com o botão direito do mouse no nó raiz e estender esse script. Ok, então isso vai nos dar nosso script EXP Pickup two D, que se estende da coleta dois D. E então vamos até o topo e diremos o nome da classe EXP Pickup two D. Então, queremos dar uma variável para a quantidade de EXP que realmente vamos obter sempre que o personagem usa Tri take sempre que o personagem usa Então, no Export VR, será um número inteiro, e nós o padronizaremos para um E agora, se olharmos para o script D pickup two, queremos pegar essa função e implementá-la adequadamente em nosso script de herança Então, vou copiar isso e vamos até o EXP Pickup two D. Vou colá-lo e escrever nosso verdadeiro método tri take Portanto, o captador EXP aplicará a experiência ao alvo se o alvo realmente tiver Então, digamos que se ptarget dot stats for igual a null, retornaremos false aqui Caso contrário, podemos dizer que var stats é igual a ptarget dot stats E como não sabemos o que essa variável de estatísticas realmente significa no contexto de cada script, vamos atribuir a ela diretamente o hype do controlador de estatísticas Então, quando a condição for atendida, que esse é um alvo que tem um bloco de estatísticas, podemos dizer que experiência com pontos de estatísticas mais experiência é igual a experiência e, em seguida, retornaremos verdadeiro Então, depois de adquirirmos a experiência, não queremos que o captador possa ser usado novamente, então direi que monitorável é igual a falso e, em seguida, avisaremos o objeto. Então, quando você ficar livre, vai passar algum tempo até que ela seja finalmente removida da cena Por isso, queremos ter certeza de que nada mais que entrar nele nesse quadro singular possa acidentalmente captar o captador EXP Então, estou tornando o monitorável falso aqui para que nada mais possa detectar Apenas como uma salvaguarda, e então removemos completamente da cena Então, essa parte aqui, eu provavelmente quero reutilizá-la em todas as minhas picapes Vou cortar isso no captador dois D e, em seguida, dizer a função remove, que retornará nula, e vou fazer essa etapa de encerramento Então, agora, se eu voltar para o EXP pickup, eu apenas chamo remove, que é proveniente da Portanto, essa função já está escrita na classe base e podemos reutilizá-la aqui Então, tipo, sim, sempre que implementarmos o banal, se quisermos refazer isso, podemos simplesmente remover aqui E para que isso funcione, precisamos adicionar as estatísticas experientes ao nosso controle de estatísticas Então, no controlador set, vou criar essa propriedade EXP. Ok, então vamos ter a experiência de Vara e o solo padronizar para zero como um número inteiro Ok, e meio que de acordo com o take damage, em que chamamos o conjunto invencível separadamente da configuração do HP, talvez eu prefira não criar um setter Em vez de usar a função e a experiência, daremos uma quantia. Então, o valor P é um número inteiro e retornaremos vazio aqui. Então, queremos aproveitar a experiência mais a quantidade de P. E então, para fazer isso, verifique se há aumento de nível. E também podemos dizer que a impressão é uma experiência aqui. Então, obteremos a experiência total coletar itens do mapa no console. E então, para atualizar o captador de EXP para isso, quero fazer estatísticas para adicionar experiência e experiência Ok, então estamos sendo um pouco mais explícitos. Portanto, essa função implica que qualquer coisa relacionada à experiência que precise ser alterada ao adicionar experiência ocorrerá, o que significa que verificaríamos se havia um aumento de nível e assim por diante. E eu acho que isso teria algum benefício. Como se pudéssemos alterar o valor da experiência sem acionar ou verificar automaticamente uma subida de nível, se precisássemos disso mais tarde Em vez de sempre fazer isso, não importa o que aconteça, como fizemos com o HP setter, onde ele sempre atualiza sua vida Ambas as formas de fazer as coisas são válidas até certo ponto. É mais ou menos sobre como você deseja expressar sua intenção aqui E você quer esconder o fato de que definir a experiência também desencadearia uma subida de nível ao colocá-la em um criador de experiências, ou você quer ser mais explícito com a função de adicionar experiência 33. L32 Configurando o Collector2D e corrigindo animações do player: Para colocar a experiência em nosso controlador de estatísticas a partir do Pickup two D, precisamos do nosso nó coletor two D, que coletará captadores para captadores Então, vamos para a cena do jogador. Vou clicar com o botão direito no player. Adicionamos um nó secundário. Vamos procurar uma Área dois D. Então, essa área dois D, eu vou renomeá-la aqui para ser coletor dois D. E então vamos clicar com o botão direito do mouse em anexar um script Então, o roteiro vai ser em personagens, então eu vou realmente colocá-lo em personagens. Pode haver um caso em que realmente façamos com que um inimigo consiga pegar objetos, mas não quero que seja totalmente específico para um jogador. Então, vou colocar o roteiro lá. Vamos criar. Em seguida, no canto superior esquerdo, daremos a ela o nome de classe collector two D. O que nos importa com a área coletora dois D é quando um captador entra no espaço Então, diremos que a função underscore ready retornará void, e diremos que a área inserida dot connect na área inserida Em seguida, criaremos a função de retorno de chamada. O sublinhado na área inserida receberá uma área P, área dois D como parâmetro e retornará Portanto, se a área P for um captador de dois D, faremos com que o ponto Tri da área P pegue em nosso nó raiz Portanto, nosso nó raiz é nosso jogador. Poderíamos exportar nosso nó raiz aqui na raiz do objeto de exportação é o nó dois D, eu suponho. E então enviaremos essa raiz do objeto aqui. Como o objeto TriTek, aquele pelo qual queremos passar Agora, em nosso inspetor, assine o jogador aqui, e isso pode realmente ser tudo o que precisamos Então, vamos adicionar uma cópia do nosso captador EXP ao mundo do jogo Vamos colocar alguns, na verdade. Então, vou clicar com o botão direito do mouse em Mundo. Vamos criar um nó dois D. Vou renomear esses captadores e depois adicionarei alguns captadores ao mundo do jogo Então, um, dois, três, e depois vou colocar tudo isso no pai da picape Podemos ver que são bem grandes. Por enquanto, tudo bem, mas provavelmente vamos reduzi-los pelo resto do jogo. Então, antes que eles funcionem, lembro que não configuramos o colisor no player Para o coletor dois D, clique com o botão direito do mouse em um nó filho e queremos a forma de colisão dois D Então, à direita, adicione uma nova forma de círculo e reduza-a para talvez exatamente ali, um pouco maior do que a forma normal de colisão Vá até o coletor TD e pegue a colisão. Vamos mascarar a camada de captação e depois desativar a camada de máscara um mundo e a camada de colisão um Esse deve ser um script somente de monitoramento. E acabei de notar que essas molduras brilhantes têm tamanhos diferentes para nossas animações, elas não estão alinhadas corretamente no centro Tipo, o ídolo parece bom, mas correr talvez esteja um pixel para a direita, e então a morte também está um pouco incorreta Então, uma maneira de corrigir isso para garantir que estejam todos corretos é atribuir uma propriedade de posição a cada um dos SprikeFrames, o que parece que eu já fiz aqui para a Portanto, Idle tem seu próprio valor. Deixe-me ver o que acontece se eu realmente remover essas propriedades de posição. Então faça isso para o Death Idol e fuja, ok? Em seguida, também o removeremos para reinicialização, se estiver lá. Ok, então, sim, parece precisamos personalizar isso novamente. OK. Então, vamos começar com a corrida. Vou posicioná-lo aqui em menos 30 e enquadrá-lo nessa animação Vamos para Idle. Vou pressionar W e mover isso para baixo. Então, é mais ou menos 13 e o quadro-chave. Ok, vamos correr. Vamos para Idle. Parece que o Idle ainda está com um pixel de altura, então vou movê-lo para menos 14, no quadro-chave Acho que era isso que tínhamos antes, mas também vou fazer a corrida e movê-la para a esquerda e enquadrá-la. Então, agora, se alternarmos entre ocioso e executado. Ok, isso realmente parece correto agora. Vamos morrer e movê-lo aqui para a direita e enquadrá-lo. Então, são dez pixels para a direita. E agora passamos para o modo inativo. Ok, a morte é um pixel à direita a mais. Então, isso precisa ir para menos nove, quadro-chave. Então, temos ociosidade. Ok, então precisamos colocar mais dois pixels para a esquerda para a morte e enquadrá-la. Então isso é um oito, e então o inativo é zero para X. Ok, tudo isso parece que está se alinhando OK. Então, aqui estão os valores reais. Oito menos 14 pela morte. O ídolo é zero menos 14. A corrida é menos um e menos 30. E então o reset, que deve corresponder ao ídolo, que é zero, menos 14 Portanto, o reset diminuirá para menos 14. O negativo 14 está aí, Keyframe it. Ok, e isso deve resolver todos os problemas de animação que estamos tendo com essas planilhas de sprites Ok, agora de volta ao coletor dois D. Certifique-se de desligar a camada um e a máscara da camada um também Ok, e agora podemos clicar em play e ver se podemos realmente pegar esses pequenos ícones. Então nós pegamos esse. Vamos verificar a saída. Conseguimos a experiência? Sim, nós fizemos. Temos uma experiência lá. Vamos descer até aqui. Temos a experiência dois. Agora, essa experiência é três, para que possamos confirmar que nossos captadores estão funcionando com base na saída do console E nosso personagem foi derrotado em segundo plano. Mas isso é bom, isso mostra que esse sistema de game over também estava funcionando. 34. L33 Criação de mecânica de solta de inimigo e redimensionamento de captadores: Nossas picapes. Agora, queremos garantir que os inimigos realmente os derrubem quando forem derrotados. Provavelmente também queremos redimensionar rapidamente o captador dois D porque ele tem o dobro do tamanho do nosso player neste momento Então, no EXP pickup two D, posso mudar o sprite animado para a versão 16 por 16, que é conveniente porque já temos isso, ou posso pegar o nó e reduzi-lo Então eu posso fazer isso como 0,50 0,5. E então essa seria uma forma de fazê-lo encolher. Mas se já sabemos que o tamanho não será consistente em nosso jogo, talvez faça mais sentido entrar na cena base de pegar dois D trocar o sprite animado E então adicionamos o mesmo ícone, mas do pacote de 16 por 16. Então, entre na folha Sprite completa dos ícones de arte, 16 por 16. Dimensione como 16 por 16 porque essa é a folha de sprite menor E então controlaremos o rolo de mouse de metal, aumentaremos o zoom, encontraremos o sprite, adicionaremos e removeremos o grande Então selecione zero e exclua isso, e então ele descerá para o quadro zero. Guarde isso. E então, nessa cena, você também pode salvá-la, e ela deve ser boa para a visão de mundo Ok, agora é o tamanho apropriado. Ok, então vamos entrar na cena dos orcs e adicionaremos a habilidade de soltar itens Então, aqui, queremos um script que manipule itens que podemos colocar no jogo, e talvez queiramos selecionar aleatoriamente de uma lista de itens, e podemos pesá-los da mesma forma que fizemos quando esperávamos a aparição do inimigo. Então, vou clicar com o botão direito do mouse no estado de morte, pois isso estará diretamente ligado ao estado de morte no sentido de que soltamos itens após a morte, e adicionarei um nó filho. Então, faça um nó regular aqui. Em seguida, vamos renomear isso para algo como drops. Clique com o botão direito, adicione um script e, em seguida, aqui, vamos criá-lo. Então, daremos a ela o nome da classe drops. Então, daremos a ela o nome da classe drops. Ok, e em nosso script de descarte, vamos querer basicamente uma lista de itens que podemos descartar. Então, digamos que, no Export VR, usaremos as definições de drop, e essa será uma matriz de definições de drop. Então, seguindo o mesmo padrão de antes, onde temos um recurso definido pelo editor, podemos repetir isso novamente, então, no sistema de arquivos, vamos querer ir a algum lugar como a pasta de coleta de objetos, clicar com o botão direito do mouse e criar um novo script E vou chamar isso de definição de queda. E isso se estenderá a partir do recurso. Crie isso. Agora podemos abrir a definição de drop, dar a ela o nome de classe drop definition. E vamos querer uma cena de Export VR, que é uma cena lotada. Então, o que estamos colocando no mundo do jogo, a entrega real do item Então, como é uma cena lotada , pode realmente ser qualquer coisa que tenha um nó em sua raiz. Você poderia derrubar inimigos se quisesse. Portanto, essa embalagem apenas a torna flexível. Ok, e depois queremos um peso. Portanto, o peso da barra de exportação está flutuando. Vamos padronizar isso para 0,1, e esse é um começo decente. Então, entraremos no script de descarte novamente e teremos nossa matriz de definições de descarte para que possamos clicar em descartar. E se você não consegue ver a matriz aqui e o inspetor aqui, basta ir ao Projeto e recarregar o Ok, agora se você verificar o inspetor, ele deve aparecer lá, desde que você não tenha nenhum erro Então, criaremos nossa primeira definição de gota. Então, nova definição de queda, e podemos fazer dela uma academia EXP com um peso de um, se quisermos. Carga tão rápida. E vamos procurar o captador EXP dois D enter, e isso configura isso Então, nosso orc só conseguirá soltar as joias de EXP, e isso é perfeitamente bom para nosso Então, se quisermos funcionar, podemos invocar nosso estado de morte ou nossa animação que seria capaz de gerar as quedas no mundo do jogo. Então, poderíamos dizer que a função drop se você quiser, você pode passar várias vezes aqui, como P vezes é um número inteiro, e isso pode ser padronizado para um, e isso retornará void Então, poderíamos dizer quatro vezes no intervalo de zero a P vezes, incrementando em um a cada vez Então isso significa que começamos do zero, subimos uma vez até chegarmos a P vezes. Então, se P vezes for um, isso será executado uma vez porque fará zero e, em seguida, atingirá P vezes e parará. Então, vamos fazer o cólon lá. Ok, e depois de fazer o loop, precisamos gerar uma queda a cada vez. Portanto, provavelmente seria melhor calcular o peso total uma vez e depois usá-lo aqui. Então, vamos gerar o peso. Então, antes de gerarmos as quedas, vamos dizer quatro definições de DF e drop Vamos acumular o peso total, então precisamos de uma variável acima disso Até agora, o peso total, há um flutuador que começa em zero, zero, e esse será o peso total mais igual ao peso do ponto DF. Está bem? Então nós temos isso. Agora, dentro desses quatro circuitos na parte inferior, estamos passando por eles todas as vezes. Queremos obter nosso peso selecionado entre zero e o peso total. Então, está meio que repetindo a mesma lógica outras randomizações que fizemos neste curso Então, digamos que o peso selecionado de var seja igual a rand F, que é 00-1 0,0, e multiplicaremos esse valor pelo nosso peso total, que nos dará Então, agora, para cada uma das quedas para definição nas definições de gota, adicionaremos o peso até agora. Até agora, o peso atual, que é flutuante e começa em zero, zero, diremos que o peso atual mais é igual ao peso Ok, então isso nos dá o que estamos fazendo até agora. Se for maior que o peso selecionado , queremos retornar essa gota ou adicioná-la a uma matriz de gotas. Portanto, se o peso atual for maior ou igual ao peso selecionado, esse é o que queremos acrescentar a uma matriz Então, vamos criar uma matriz aqui acima do loop de quatro, e vamos dizer que var drops é uma matriz de definição de queda. Agora, o principal aqui é que isso pode ter várias cópias da mesma definição de descarte. É uma matriz, não algo como um conjunto de hash. Portanto, podemos ter a mesma queda duas ou três vezes, se necessário, o que é importante. Digamos que drops dot acrescente a definição, e então saímos desse loop de quatro, e então ele voltará aqui Então, quando chegamos ao ponto em que o peso atual é igual ou maior que o peso selecionado, escolhemos a gota e fazemos um loop novamente cada vez que precisamos para essa configuração de queda. Agora temos todos os itens suspensos aqui, então queremos instanciá-los no mundo do jogo. Então, digamos que quatro gotas em gotas. Vamos criar uma instância que será igual a drop dot seen dot Instantiate E então vamos adicionar isso quando criança a algum pai dentro do nosso mundo de jogos. Então, no mundo, poderíamos simplesmente reutilizar esse nó de captação, se quisermos Então eu posso pegar picapes. Vamos até o nó aqui no canto superior direito e adicionarei um novo grupo. Então, vamos dizer pickups. Vou tornar isso global. Então, para qualquer coisa que seja um item a ser retirado do mundo, vamos adicioná-lo como seu grupo de nós. Então, quando está em um grupo de nós, é muito fácil encontrá-lo dentro do nosso script E podemos realmente obter esse nó de captação assim que nosso orc for carregado, então saberemos se há algum problema Então, vamos dizer var pickups parent, e esse será o nó dois D, e já diremos a função underscore e esse será o nó dois D, e já diremos a função underscore . Deixe-me ampliar aqui. O pai da coleta será igual a Gtree dot Obtenha o primeiro nó no grupo, e estamos procurando essas captações. Portanto, nos grupos Gtree dot Obtenha o primeiro nó no grupo, de nós aqui nos grupos de nós do inspetor, você pode ver que de nós aqui nos grupos de nós do as captações já existe uma, e ela está atribuída a esse nó de coleta e ela está atribuída a esse Portanto, enquanto o nó de captação existir em nosso mundo de jogo atual, ele funcionará muito bem Poderíamos dar um pequeno passo adiante e transformar isso em uma variável constante. Então, vamos dizer que grupo de captação aqui, tudo em maiúsculas, e então grupo de captação constante é um nome de string igual a, e eu direi e comercial, Controle V, cole Controle V Portanto, desde que você tenha um nó no grupo de captadores para isso e tenha atribuído esse nó ao grupo dentro do seu projeto de jogo e ele exista na cena , isso funcionará perfeitamente bem Você não precisa obter nenhuma referência direta, o que seria complicado porque o orc não existe na cena até ser gerado Portanto, essa é uma maneira decente de obter aquele nó pai para o qual podemos criar. Se quisermos ter certeza de que podemos até mesmo dizer, tipo, afirmar que pickups parent e não é igual a null, então diremos que deve haver um pai para que os itens sejam Ok, isso está bem claro. Ok, então instanciamos cada uma das cenas e, em seguida, queremos adicioná-las como crianças ao pai da picape Então, pega a mãe de uma criança Stance. E a localização em que queremos que a entrega esteja será baseada no nó dois D. Então na verdade, precisamos pegar as gotas e alterá-las para um nó dois do tipo D. Então, aqui embaixo, podemos dizer que a posição global da instância será igual à posição global do script. Ok, então isso significa voltar ao nosso cenário organizacional. Então, agora que queremos alterar esse tipo de nó, vou clicar com o botão direito do mouse e alterar o tipo, pesquisar por gotas, e você deve vê-lo aqui. Clique duas vezes. Ok, clique em Drops. Certifique-se de que, no inspetor, você ainda tenha sua definição de descarte para o EXPJM lá E provavelmente precisamos tirar isso dos nós do HSM aqui Como esse é um nó dois D, queremos que seja filho do nosso nó principal dois D, então vou trazer isso aqui como filho do trabalho. E isso provavelmente deve ser bom. Então, temos o item ou qualquer outra coisa que estamos lançando no mundo do jogo Ele se torna filho do nó do grupo de captadores e, em seguida, atribuímos a ele a posição desse nó de descartes, que é apenas um deslocamento, se houver, da posição dos orcs Não precisamos alterá-lo, mas poderíamos simplesmente ter um padrão como zero, zero aí. Tudo bem. E agora podemos chamar quedas da animação da morte ou do estado da morte. Então, se eu for até o player de animação aqui e abrirmos a animação da morte, vamos ver. Estado de morte. Então, vamos ver. Estamos chamando de estado de morte acabado. Poderíamos simplesmente colocar as gotas assim que o orc começar a morrer Acho que essa pode ser mais a forma como a maioria dos jogos acontece, em que você vê o loop antes que eles saiam em que você vê o loop da cena Então, em uma faixa, chame o método no nó de descarte. Então, aqui embaixo, no primeiro quadro. Vamos ampliar. Tudo bem, clique em Inserir uma chave. Nós fazemos entregas. Você pode ver os parâmetros funcionarem no reprodutor de animação. Então, no canto superior direito, temos nome do nosso método drop. Tenha a discussão. Portanto, o primeiro argumento e o único argumento é o valor int. Então, quantas vezes queremos ligar para o Drops? Poderíamos dizer 50 por diversão, e vamos clicar em Play e ver se isso realmente funciona. Então, isso colocará muitas dessas joias de EXP em cena se estiver funcionando, mas pelo menos definitivamente saberemos se funciona Então, vamos ver o que acontece. Ok, eu acho que todos eles simplesmente aparecem no mesmo lugar Então, vou repassar isso. E sim, você pode ver que pegamos 50 gemas 35. L34 Gerando posições aleatórias de itens: Bem, quando o orc derruba 50 desses itens, eles ficam todos empilhados uns sobre os outros, se eu verificar a saída Então, temos 50 XP lá. E acho que o que gostaríamos de fazer é que, quando o objeto aparecer, façamos um deslocamento ou façamos com que ele se afaste do Está caindo um pouco. Então, acho que a maneira mais rápida de fazer isso seria gerar uma posição de deslocamento aleatória, e isso estará a um certo número de pixels de distância do personagem em uma direção aleatória Então, podemos simplesmente adicionar isso ao script drop. No topo, vou exportar nossa distância máxima de queda, que será um flutuador E vamos usar dez pixels por padrão. Isso representará a distância do nó de descarte. Esse é um nó específico em que estamos trabalhando, no qual o objeto pode aparecer, e essa é uma quantidade máxima, então pode ter de 0 a 10 pixels Então, aqui embaixo, vou criar uma nova função. Vou chamá-lo de function, underscore, get span, offset E isso passará em uma distância P max, que é uma flutuação, e podemos padronizar isso para a distância máxima de queda. Portanto, não precisamos passar um parâmetro. Pode ser que seja isso por padrão. E então queremos retornar ao vetor dois como o deslocamento. Então, para obter um deslocamento final, precisamos da direção e, em seguida, da magnitude, a magnitude está aqui na distância P max. Então, digamos que a direção var seja um tipo inferido do vetor dois, e vamos criar um novo vetor dois, então coloque-o entre parênteses aqui, precisamos de um X e um Y. Então, para obter isso, basicamente precisamos gerar uma direção aleatória entre menos um Então, vou dizer rand F, e acho que precisamos de um intervalo aqui porque queremos ir menos 1,0, não zero a um Portanto, o intervalo aleatório de F em menos 1,0 a 1,0. E então precisamos fazer isso uma segunda vez para que possamos simplesmente copiar essa linha para o valor Y até aqui. E então eu quero normalizar o vetor para que seja uma direção pura Ok, então agora temos nossa compensação. Então, o deslocamento var será igual à direção vezes a distância P max. E então retornamos o deslocamento, e é basicamente isso. Então, pegamos Get spawn offset aqui e, quando definimos a posição global, vamos fazer a posição global mais GitSpawnOfset O padrão é a distância máxima de queda, então podemos usá-la como padrão aqui. Então, na verdade, você não precisa passar pela distância máxima de queda, mas você poderia. Então, seria apenas o valor se sobrepondo. De qualquer forma, será o mesmo, mas você tem a opção de deixá-lo em branco e, em seguida, esse valor será o padrão aqui embaixo. Acho que é tudo o que precisamos. Então, vamos entrar no modo de jogo e ver se esses 50 itens realmente caem em locais diferentes. Então, vamos clicar em play e entraremos aqui. Vou atirar uma flecha ou lança no orc. E podemos ver que todos eles aparecem em direções aleatórias Mas eu realmente cometi um erro. Portanto, não queremos normalizar o vetor porque quero que a porcentagem da distância seja capaz de ir de 0 a 100% Ok, então, como eu normalizei o vetor para a direção, ele sempre fornecerá a distância máxima total aqui Essa será apenas a direção pura. Mas o que eu realmente quero é que, quando tomar essa direção, seja uma porcentagem da distância. E talvez queiramos chamar isso mais como um vetor aleatório. E então vamos descer para compensar aqui e depois disso. Então, quando está tomando o X, ele estará em algum lugar de 0 a 100% da distância no X multiplicado pela distância máxima de P e o mesmo para o Y. Então, isso dará a ele uma posição mais aleatória dentro de um Se você criasse uma forma de colisão, seria mais ou menos assim para os possíveis locais de extensão Então, vamos entrar no modo de jogo, e deve estar mais correto agora, quando derrubarmos todos os 50 itens ao mesmo tempo. Então aí está. Eles são todos gerados aleatoriamente dentro desse círculo Na verdade, nunca vamos descartar 50 itens ao mesmo tempo. Então, isso parece meio estranho. Mas se houver duas ou três gotas, acho que funcionará muito bem. Então, para demonstrar, vou até o player de animação e, quando morrermos, usarei a função drops aqui e mudaremos o valor do argumento de quantas gotas para algo mais parecido com três. Acho que isso é mais realista. Vamos clicar em play e depois entraremos aqui. Na maioria dos casos, acho que a maioria dos inimigos só vai derrubar um item. Mas se decidirmos descartar três, então pelo menos podemos ver que eles têm posições diferentes, e é óbvio pelo menos ver onde eles estão. Ok, então eu quero encerrar isso trocando as gotas por uma. Cada um ou só aumentará uma EXP. 36. L35 Implementando uma área de gravidade de captação: É um pouco entediante se o jogador precisar passar por cima de cada picape que você deseja pegar, especialmente quando você vai se esquivar de todos esses inimigos orcs que se estendem todos esses inimigos orcs que Então, o que queremos adicionar será uma área de gravidade de captação Então, em nossa cena de jogador, em vez de adicionar a área de gravidade ao nosso coletor de dois nós D, vou criar um nó separado de duas áreas D para gravidade especificamente A razão para isso é porque a forma de colisão de dois D aqui para realmente pegar os itens será uma área diferente daquela que está aplicando gravidade Então, isso seria meio confuso com o coletor dois D, tendo duas formas de área aqui Então, vamos criar um novo nó. Vou clicar com o botão direito do mouse no jogador para adicionar um nó secundário. Isso seria na área dois D. Vamos adicioná-lo aqui na parte inferior e vou renomeá-lo para, digamos, gravidade de captação dois D, porque isso é especificamente para itens no mapa que podem ser coletados Ok, então vamos clicar com o botão direito do mouse no jogador para adicionar um nó filho. Vamos procurar a área dois D, e eu poderia chamá-la de algo como gravidade, área dois D. Pensei em chamá-la de gravidade de captação dois D, mas queremos tornar o script um pouco mais genérico, porque pode haver casos no futuro você realmente queira que a gravidade se aplique a algo que não é um captador e lidar com a gravidade específica do captador é gerenciado apenas pela forma de colisão. Lidar com o fato de ser para atingir captadores é gerenciado apenas pelas camadas de colisão Então, tudo o que você precisa fazer para que ela atinja os captadores é escolher a máscara cinco aqui para a camada de captadores, e vamos desativar a camada um para onde ela existe e torná-la apenas monitorada Ok, então essa é a nossa configuração. Então, só precisamos, na área de gravidade aplicá-lo a todos os objetos dentro daqui que ele detecta. Então, dentro da área de gravidade, clicaremos com o botão direito do mouse. Antes de deixarmos o inspetor, porém, se olharmos para esta seção de gravidade, há uma gravidade D embutida na área dois, mas o fato é que isso se aplica ao corpo rígido de dois Ds, que são objetos físicos completos no jogo, e não queremos 1.000 corpos rígidos flutuando pela tela Então, em vez de usar a física padrão para controlar a gravidade em nossos captadores, queremos apenas um script simples façamos com que ele chegue a em que façamos com que ele chegue a qualquer lugar onde esteja o centro do jogador E não lidar com dois Ds de corpo rígido. Então, essencialmente, é uma otimização de desempenho. Não precisamos de física completa para cada um dos nossos itens de coleta. Eles só existem para serem pegos pelo jogador. Portanto, sugá-los diretamente para o player é perfeitamente normal Então, vou clicar com o botão direito em Gravity Area two D e anexaremos um script. Claro, vou chamar essa área de gravidade dois D. Vamos criar esse nome de classe. Claro, área de gravidade dois D. Ok, então enquanto um objeto está dentro da zona, queremos rastreá-lo e aplicar consistentemente um movimento a ele, basicamente traduzindo outro nó dois D pela tela em direção ao ponto central dessa área dois D, a área de gravidade dois D. Então, vamos ter uma variável local Vou chamá-lo de alvos, e isso será uma matriz do nó dois D está bem. função estiver pronta, queremos nos conectar ao sinal dessa área dois D. Então, vamos dizer área inserida, ponto conectar, sublinhado na área inserida Também nos conectaremos à área de saída da área conexão pontual na área saída Precisamos criar essas funções agora. Sublinhado da função na área inserida, e isso nos dará a área dois D como parâmetro Então, área P área dois D, estamos tentando anular aqui Ok, então o que vamos fazer com a área aqui? Vamos movê-lo em direção ao ponto central da nossa área de gravidade dois D. Isso vai funcionar bem com o captador porque as áreas de captação estão na raiz na área dois D. Então, qualquer coisa abaixo dela se moverá automaticamente em direção ao centro, então exigimos que tenha esse tipo de Caso contrário, você precisaria de uma referência ao nó pai da cena. Qualquer que seja a base da sua cena de captura é o objeto ou nó, em vez disso, que precisa se mover Portanto, esteja ciente disso. Como estamos fazendo todos os captadores especificamente dessa forma e os captadores são exclusivos da camada cinco, funcionará perfeitamente do jeito que Se você quiser ser mais seguro e quiser limitá-la apenas aos scripts de coleta , é claro que você pode verificar se a área P é do tipo pickup dois D. Não parece ser necessário, como é agora, mas é algo que você deve estar ciente Então, vou colocar um pequeno comentário lá sobre o que acabei de dizer. Ok, e já que a área P aumenta assim. Vou funcionar bem do jeito que está. Então, direi que os alvos pontilham uma caneta, área P. Lembre-se de que a área P área dois D é do tipo nó dois D, então isso funciona bem aqui. Não há necessidade de ser mais específico do que isso, porque só precisamos acessar as funções D do nó dois. Então, na área saída, função, sublinhado na área área P, área dois D, retorna vazia, então vamos dizer que os alvos apagam a área P. Agora, para observar a função de apagar, se o objeto que você está tentando apagar da matriz não existir na matriz, isso não fará Se ele apagar, ele o removerá. Portanto, na verdade, não há necessidade verificar se ele já está na matriz. Porque se não existir na matriz, isso já não fará nada. Portanto, não há necessidade de verificar novamente. Certo. E então precisamos de um processo físico. Então, digamos que a função sublinha o processo físico, e digamos que, para o alvo nos alvos, queremos traduzi-lo pela tela direção ao ponto da área de gravidade central Precisamos de uma velocidade no topo na exportação. A velocidade da gravidade é um flutuador Se bem me lembro, isso vai chegar a pixels por segundo. Então, vou tentar algo como 50,0. Em seguida, precisamos calcular a direção entre o alvo e o ponto central da nossa área de gravidade. Até agora, a direção será igual à posição global do ponto alvo , direção do ponto, direção do ponto, posição global dois. Está bem? E então só precisamos calcular nosso valor de movimento. Então, o movimento var será igual à direção vezes gravidade, velocidade, vezes Delta. Como estamos usando translação, precisamos fatorar isso diretamente aqui para o vetor de movimento final. Podemos dizer que esse é um fator dois D, se isso deixar tudo mais claro. E então queremos pegar o alvo e traduzi-lo pela tela com o deslocamento do movimento Este é essencialmente o nosso script de gravidade ali mesmo. A última coisa que acho que precisamos é adicionar uma forma de colisão à nossa área de gravidade Então clique com o botão direito na área de gravidade até D, adicione uma forma de colisão a D. Vá para o canto superior direito, uma nova forma de círculo e torne-a bem grande para que tenhamos grande para que tenhamos a área onde ela realmente aplicará a gravidade em direção ao centro Ok, então eu posso jogar, e vamos entrar aqui e você pode ver que nossos objetos são sugados para o centro Então, agora, a gravidade é linear. Talvez queiramos fazer uma curva para que, quanto mais perto ela chegar do ponto central, mais rápido ela realmente anime essa translação em direção ao centro Então, se formos para a área de gravidade dois D, e dentro daqui, direi na exportação, digamos curva de efeito do tipo curva. Vamos guardar isso. Então, no inspetor, vamos editar essa curva de efeito, nova curva E então queremos que X ou o domínio máximo aqui seja basicamente a distância do centro. E então o valor aqui será a porcentagem da velocidade máxima que você deseja aplicar com base nessa distância. Então, digamos que a distância seja como 100 aqui para o domínio máximo. Quanto mais próximo estiver, mais perto queremos chegar de 1.0. Então, vamos pegar o primeiro ponto e movê-lo aqui para 1,0. Vou ampliar aqui para que você possa ver. E então eu vou puxar um segundo ponto para baixo assim. OK. Então, se chegar a 100 de distância, ficará muito fraco nesse ponto. E isso seria medido em pixels, é claro. Então, com essa curva, queremos voltar aqui e ajustar o movimento amostrando essa curva Então, vamos pegar o modificador de curva, que será igual à amostra de pontos da curva de efeito E precisamos amostrar com a distância do nosso alvo até o centro de gravidade. Então, a distância vara será a posição global do ponto alvo, a distância do ponto até a posição global Ok, então passamos essa distância para a amostragem do modificador de curva e, em seguida, pegamos o modificador de curva e multiplicamos isso Então, esse será um valor entre 0,0 e um. E isso deve afetar a gravidade com base nessa curva. Quanto mais perto estiver, mais forte será. E aqui, fica mais fraco. Sinta-se à vontade para personalizar uma curva se precisar alterar um pouco a forma da animação. Ok, então vou clicar em play aqui e vamos testar isso. É um pouco difícil de ver porque talvez eu tenha tornado a distância máxima aqui muito grande. Então, o que você pode fazer é verificar a forma da colisão e ver qual é seu raio Então, 27 pixels. Então, estamos basicamente fazendo uma curva de até 100 pixels, mas o máximo desse raio é 54 pixels, 27 aqui Ah, sério, não, não, não, 27 pixels porque é o centro do ponto externo, certo? Não é o diâmetro, é claro. Sim, talvez eu queira pegar o raio aqui e torná-lo em 30 pixels, um bom número par, e depois vamos para a área de gravidade E então vamos pegar o ponto da curva aqui e movê-lo para 30 pixels também. Ok, então isso será como nossa distância máxima nesta forma aqui. Não precisa ser perfeitamente 30. Tipo, mais ou menos aqui, para que possamos ver a forma um pouco melhor. Ok, agora se eu apertar play e formos até aqui , deve ser um pouco mais preciso. Ok, agora você pode ver a gravidade realmente aumentando à medida que se aproxima, então é lenta por fora, quase lenta demais. Então, eu poderia realmente aumentar isso um pouco, e você pode ajustar a forma da curva puxando as alças, o que quer que você precise fazer. Veja, eu meio que gosto disso. Vamos tocar em play mais uma vez só para testar. E sim, eu acho que isso é certo para a gravidade. Então aí está. Escalando a gravidade Quanto mais perto seu objeto estiver de ser jogado, mais rápido ele se moverá e absorverá todos os itens coletados ou, na verdade áreas que você marcar na camada da máscara aqui marcar na camada da O que, neste caso, agora são apenas captadores, mas você pode fazer isso com outras áreas 37. L36 Como criar uma UI de player com barras de progresso HP e EXP: Ok, então, embora o combate principal esteja funcionando no jogo, podemos pegar itens como captadores de EXP, mas não temos nenhuma indicação na interface do usuário do que está acontecendo Não podemos ver o nível do nosso personagem, nosso HP, nossa barra de EXP. Então, vamos começar trabalhando na barra de EXP e adicionando um contador de nível, digamos, no canto superior esquerdo da tela E vamos fazer isso em um novo nó. Então, vou subir até a seção intermediária e adicionar uma nova cena. E queremos que isso seja uma interface de usuário. Então, vou chamar esse player de UI. Vamos salvá-lo na pasta UI. E guarde-o lá. Em seguida, vou clicar na interface do player e adicionaremos, digamos, um contêiner de painel. Então, esse será essencialmente o fundo da nossa interface de jogador principal. Agora, você diz que a interface do player se estende por toda a tela por padrão Então, queremos entrar no layout à direita e alterar a predefinição de âncoras de totalmente destruída Ok, agora, isso reduzirá o tamanho aqui para basicamente nada E então queremos fazer o dimensionamento do contêiner, expandir no preenchimento horizontal e vertical Em seguida, em nosso contêiner de painel, queremos clicar com o botão direito do mouse e adicionar um novo, digamos, um contêiner de caixa V. Um contêiner VBox organiza seus filhos verticalmente. Então, se você colocar dois itens aqui, o que está diretamente abaixo dele ficará em cima do outro em termos de layout visual. Então, vamos clicar com o botão direito do mouse no contêiner VBox e agora eu quero um contêiner HBox Portanto, nosso contêiner HBox, o primeiro, irá da esquerda para a direita, e estará em cima de qualquer outro contêiner HBox infantil Então, isso nos ajuda a organizar as coisas quase como uma grade, mas não exatamente. Ok, e então, como filhos do contêiner HBox, queremos adicionar uma barra de progresso de textura para que você possa pesquisar Progress e encontrará aqui Isso permite que você, no canto superior direito, defina texturas para a textura inferior, a textura superior e a textura progressiva Assim, à medida que os valores forem preenchidos, ela mostrará mais ou menos da textura de progresso e, abaixo dela, estará a textura base, que sempre aparece em segundo plano. Ok, e além disso, queremos um rótulo à direita disso. Então, vou clicar com o botão direito do mouse no contêiner HBox e adicionar um rótulo. Um rótulo básico deve estar bem aqui. Sempre podemos alterá-lo para um rótulo de rich text posteriormente. Ok, e agora, para essa barra de progresso de textura, queremos encontrar a arte da nossa barra de progresso. Então, vamos minimizar tudo no canto inferior direito e expandir a pasta de arte. Vamos para a GUI do Crimson Fantasy. E eu acho que foi sob o GI Sprite aqui. Então, no canto superior direito para baixo, vou criar uma nova textura de atlas e depois expandi-la E vamos arrastar o GI Sprite para o atlas aqui. Assim, podemos ver o atlas completo, estilo de arte gótica muito legal acontecendo aqui E podemos selecionar o que queremos que seja nossa subtextura. Portanto, a textura inferior será basicamente nossa barra, onde estará completamente vazia. Então, se eu editar a região, posso ampliar aqui e selecioná-la, mas aqui, dessa forma, essa pode ser nossa textura inferior ao toque de perto. E então, para o rótulo, digamos que zero em 100 HP por enquanto, apenas como uma maquete Portanto, agora faz sentido renomear esse contêiner HBox, algo como o monitor HP E vamos duplicá-lo e, em seguida, renomearei o segundo para ser EXP Vá até a barra de progresso da textura. E nas texturas, vamos selecionar uma diferente na região Editar Então, vamos ver o que gostamos aqui como barra de EXP? Poderíamos usar esse básico aqui, mas acho que seria útil se pudéssemos ver partes diferentes Então, com este, podemos ver em sete o quão perto estamos de realmente subir de nível Mas você notará que, assim que eu alterar o valor aqui para este, o primeiro também será atualizado automaticamente porque estamos usando um recurso compartilhado de textura de atlas Então, o que realmente temos que fazer aqui, vou fechar, é clicar com o botão direito do mouse nessa textura e , em seguida, torná-la única. Então, quando você fizer isso, essa textura será única. Precisamos voltar ao primeiro e corrigi-lo, clicar com o botão direito do mouse e, em seguida, criar Exclusivo, e precisamos mudar o HP de volta para sua textura HP. Então, aqui, selecionaremos essa barganha da HP e agora podemos ver que essas são duas coisas distintas Ok, agora vamos também fazer o preenchimento do primeiro. Vou progredir aqui, nova textura do Atlas, e então podemos carregar rapidamente, a partir do menu suspenso, nosso sprite da GUI E agora queremos editar a região e pegar a barra de saúde preenchida aqui. Ok, então vai ficar mais ou menos assim e clique em Fechar. Agora que temos esse conjunto de texturas, se você acessar, digamos, valor aqui e digitar 50, verá que parte da barra de saúde agora está preenchida. Mas você também vê que, com essa configuração, isso pode ser parcialmente porque o coração está escondendo coisas, mas na verdade não parece que esteja refletindo com precisão 50% de sua saúde total aqui quando o valor é 50 Então, para contornar isso, o que eu estava fazendo era mudar o valor dos homens algo como menos 20 para algo como menos 20 para compensar isso para a direita Então, agora você pode ver que há quatro de saúde visíveis em oito Então, esse valor de 50 faz muito mais sentido quando você tem esse deslocamento negativo de 20 Então, talvez você precise personalizar isso. Então, obviamente, quando você caracteriza zero saúde, vai mostrar que zero é o valor que estará aqui Mas o que realmente importa é como os 50 de 100 aqui e os 100 de 100 ali. Então, só para garantir que valemos 100 para uma barra de saúde totalmente preenchida , e isso parece bom. Podemos dizer 20. Ainda podemos ver nossa saúde. E mesmo às cinco ou dez, bem, acho que às cinco, não precisamos ver isso necessariamente. Mas, aos dez anos, ainda podemos ver uma pequena lasca. Eu acho que, do jeito que está agora, é muito bom. Então, na verdade, podemos deixar esse padrão como 50. E vamos trabalhar na textura da tela EXP. Vamos clicar com o botão direito na base abaixo da textura aqui, copiar e clicar com o botão direito do mouse no progresso vazio e colá-lo. Em seguida, queremos clicar com o botão direito do mouse aqui e torná-lo único e alterá-lo para o valor de que precisamos. Então, edite a região, e queremos pegar essa versão preenchida dessa barra. Está bem? E podemos digitar 50 para o valor do teste. Ok, e então podemos ver que está meio preenchido. Então, tudo bem. Não precisamos fazer um valor mínimo negativo nessa versão da textura. Há um pequeno problema aqui em que nossa barra de progresso para o XP está vermelha, assim como a que está no topo. Então, o que realmente queremos fazer é que essa parte de metal seja tingida com uma cor diferente Então, como podemos fazer isso é ir até a tonalidade de progresso e alterá-la para mais verde, mais ou menos assim Mas você pode ver que isso realmente tinge toda a textura Então, o que queremos fazer é clicar com o botão direito na textura inferior, controlar a cópia e, em seguida , colar na textura superior. Ok, agora apenas os pixels que não existem na parte inferior e superior serão afetados pela alteração da textura do progresso. Então, seja qual for a cor que você quiser que o progresso seja, você pode simplesmente alterá-lo para essa simplesmente manipulando a tonalidade aqui. Pode mudar a escuridão, e isso provavelmente é bom o suficiente para sua barra de XP, para ser honesto, a solução mais simples sem usar um sombreador nem nada Então, se formos para o rótulo agora, queremos mudar isso para dizer EXP. Então, zero em 100 EXP. Ok, e então queremos centralizar verticalmente essas barras de progresso de textura Acho que você pode selecionar os dois ao mesmo tempo mantendo a tecla Control pressionada, clicar com o botão esquerdo do mouse e seguida, ir para o tamanho do contêiner de layout e alterá-lo de preenchimento vertical para centro de redução Sim. OK. E então isso basicamente pega esses e se concentra em relação aos outros elementos como esse rótulo aqui à direita . Então, isso vai ficar bem. Então, só queremos reduzir o texto. Então, o que talvez queiramos fazer, na verdade, é acessar a interface do jogador na raiz aqui e alterar o tema se carregarmos rapidamente do menu suspenso o tema do nosso jogo. Então, ele terá aquela fonte de pixel art, que já é por padrão, um pouco menor. Ok, a última coisa para finalizar nossa maquete que provavelmente queremos um contêiner de margem tão aparente quanto o contêiner do painel Então, clique com o botão direito nas raízes, interface do jogador, adicione um contêiner de margem. Então, pesquise a margem e, em seguida puxe o recipiente do painel por baixo dela. Agora, no contêiner de margem, você pode acessar as substituições de tema nas constantes corretas e personalizar Então, vou escolher cinco para todas as margens de direção. Ok, mais ou menos assim. Então, essa é provavelmente uma margem suficiente, mas na verdade eu errei no pedido. O contêiner do painel fica abaixo da interface do player e, em seguida, o contêiner de margem fica abaixo do contêiner do painel e, em seguida, o contêiner do VBox fica abaixo dele Ok, então a questão é que queremos que o contêiner do painel estique a imagem de fundo até as bordas aqui, e então queremos que todo o resto esteja contido nele. É por isso que o contêiner de margem precisa estar dentro do contêiner do painel, que o contêiner do painel possa se estender mais do que o contêiner da margem. É só uma coisa de pedir. Então, isso vai ser bem decente. Vamos colocá-lo em nosso mundo. Então, em nosso cenário mundial, vamos criar uma camada de tela para colocar a interface do usuário. Então, clique com o botão direito do mouse em adicionar um nó de camada Canvas agora. Ok, e a razão pela qual você teria uma camada de tela aqui é que ela fornece uma área de renderização separada de tudo o mais na cena Portanto, a interface do usuário é renderizada de forma totalmente independente do mundo do jogo Toti E isso seria importante se você tivesse, digamos, luzes de jogo Toti e não quisesse que isso afetasse a interface do usuário Você quer que eles sejam renderizados separadamente. Portanto, as luzes para o mundo são diferentes de se você tiver alguma luz para a interface do usuário, isso seria uma coisa diferente. E você meio que os gerencia separadamente. Então, agora vou querer adicionar a interface do player aqui, então filtre seus arquivos, pesquise a interface do player Underscore . Se foi isso que você deu como nome, Dragon solte a cena na camada Canvas e ela aparecerá no canto superior esquerdo da nossa interface Antes de clicarmos em Play, certifique-se de que interface do player esteja abaixo da camada Canvas. Isso será importante para que não seja renderizado também no mundo do jogo, mas sim como parte da tela. Então está lá no canto superior esquerdo. Na verdade, é bem pequeno. Isso é muito hilário, se eu for honesto. Podemos aprimorar a interface do usuário aqui ou aumentá-la na cena base Então, talvez o que eu queira fazer seja pegar a camada de tela aqui e vamos transformar, aumentar a escala para, tipo, quatro X. Você pode diminuir o zoom. Procure a caixa forrada de roxo. Você pode realmente ter que esconder, tipo, o mundo terrestre para que ele realmente o veja. Ok, aí. Então, temos a caixa roxa aqui. Esta é a área de visualização completa da porta. Então, sua interface de usuário aqui é meio que relacionada a isso. Então, em uma escala de quatro vezes, acho que funciona muito bem. Agora vou mostrar a sujeira e a grama novamente. Vamos clicar em Play. E vamos ver se a interface do usuário está bem no canto superior esquerdo E eu acho que esse tamanho é realmente bastante decente. Estou gostando muito disso Vamos continuar com isso por enquanto e depois trabalharemos na criação de um script. 38. L37 Implementando um sistema de UI baseado em estatísticas com sinais: Então, para que essa interface realmente funcione, precisamos conectá-la a sinais relacionados ao bloco Sp do nosso personagem. Isso significa que precisamos de um sinal alterado de EXP ou de um sinal alterado de HP Queremos ter certeza de que atualizaremos isso. Também temos outro pequeno problema, que é que basicamente essa interface de usuário é muito grande na área da tela em que está atualmente. Então, quero adicionar rapidamente um script em que eu possa fazer com que a camada Canvas seja exibida automaticamente quando o jogo começar, mas, opcionalmente, podemos simplesmente desativá-la quando formos Portanto, não quero sempre ter que ativar manualmente a visibilidade. O que vou fazer é clicar com o botão direito do mouse na camada Canvas aqui e anexar um script. Então isso seria apenas canvaslayer dot GD. Vamos salvar isso na pasta Bin da interface do usuário. Criar. E vou apenas dizer que a função sublinhado está pronta. Ele retornará vazio e, em seguida, diremos visível, igual E isso é tudo o que precisamos para isso. Então, agora podemos escondê-lo quando estamos vendo nossa visualização do mapa aqui e clicar em Play. E ainda deve aparecer assim que o jogo começar. Então, agora podemos escondê-lo da nossa visualização do mapa aqui, clicar em play, e ele ainda aparecerá assim que o jogo começar. Então, no canto superior esquerdo, lá está. Então, isso será útil enquanto estivermos editando. Outra maneira de lidar com isso seria ter uma cena completamente separada para sua interface de usuário do Canvas ao editá-la, depois sua cena mundial e combiná-las em uma cena principal. Quando você realmente carrega o mundo do jogo, tudo bem. E talvez essa seja a solução a longo prazo. Mas essa é uma solução muito boa, rápida e fácil. Então, vamos trabalhar para conectar nossa interface de jogador às estatísticas do jogador. Então, vamos entrar na cena da interface do jogador. Vou clicar com o botão direito na interface do jogador. E anexe um script. Assim, o playi dot gD pode estender o controle e o interior daqui Vamos apenas exportar R e diremos o contexto do jogador. Como já criamos esse recurso, ele é muito fácil de usar. E o inspetor aqui no canto superior direito, basta carregar rapidamente o contexto do player E se você se lembrar do início do curso, o jogador se instalará automaticamente lá, então podemos simplesmente pegar o ponto de contexto, as estatísticas de pontos do jogador e pronto, temos uma referência às estatísticas. Só precisamos de sinais para atualizar a tela HP e a tela EXP. Ok, então podemos consultar as estatísticas. Vamos ver, ponto do controlador de estatísticas GD. Se entrarmos nesse roteiro, teremos uma vida alterada. Vamos criar alguns sinais de que a HP mudou, Max HP mudou e a experiência mudou. Ok, então o sinal Mx HP mudou. E você pode ver que são muitas estatísticas que vamos mudar com um tipo muito semelhante. Talvez queiramos passar o objeto que estava sendo alterado, o valor antigo, o novo valor e o valor da alteração. Então, podemos realmente criar uma classe para encapsular todas as nossas estatísticas que vão mudar E esse é um sistema de jogo muito baseado em estatísticas, tipo Survivor, certo, porque você pode reduzir o tempo de resfriamento, pode ter velocidade de movimento do jogador, HP, poder de ataque, todo esse tipo de coisa extra E todas essas são estatísticas que podem ser representadas dentro de um objeto que podemos passar para um evento. Também é muito mais fácil se você tiver apenas um parâmetro para enviar esse parâmetro e, em seguida, eles receberem como uma peça, em vez de três ou quatro. Então, para mostrar o que quero dizer, vamos criar um novo script em nosso sistema de arquivos. Então, vou derrubar tudo e, em seguida, entraremos, digamos objetos porque objetos têm estatísticas. Então, vou clicar com o botão direito do mouse e criar um novo script. Então, esses serão dados que emitirão um sinal sempre que uma estatística for alterada Portanto, um nome bem claro seria stat changed data dot gD. Nós criamos isso. Ok, e vamos abrir esse script. Então, os dados foram alterados por estatísticas. Nome da classe, dados alterados por estatísticas. E isso, na verdade, se estenderá a partir de ref count, que é um objeto que, quando não for mais referenciado, será automaticamente excluído do jogo Então, referências. E em vez de estender não, isso na verdade se estenderá a partir de ref count, que é um objeto Gadot que monitora quantos objetos estão fazendo referência E quando nenhum objeto faz mais referência a ele, ele basicamente se enfileira para ser excluído, então você não precisa liberá-lo manualmente Ele será simplesmente coletado e excluído pelo motor. A propósito, isso também é o padrão para quando você não se estende de nenhuma classe, essa também é a classe padrão. Ok, então nossa estatística mudou os dados, queremos dar a eles uma função de inicialização, para que a função sublinhe E quando criamos um NIT para um objeto, podemos transmitir quaisquer parâmetros de que precisamos Então, vou dizer objeto P, o objeto que estamos afetando com nossa mudança de estatísticas Então, sem TD, o valor P Nu, que eu acho que será um número inteiro no momento Pode haver uma estatística flutuante. Nesse caso, você pode alterar esse tipo para uma variante para suportar números inteiros e Mas acho que, no momento, não haverá realmente nenhum carro alegórico acontecendo no jogo para estatísticas como experiência e HP Nós os transformamos em números inteiros concretos, que provavelmente é preferível Então, o novo valor que estamos passando e, em seguida, queremos o valor antigo. E quando temos o valor novo e o antigo, podemos calcular automaticamente a alteração. Então, vamos inserir as propriedades de estado desse objeto. Eu direi que o objeto var será um nó dois D, o var new será um inteiro O var old será um número inteiro. A alteração de var também é um número inteiro. Então, quando inicializamos a função, simplesmente pegamos os parâmetros e definimos as variáveis locais com esses valores Então, o objeto será igual ao objeto P. Um novo vai ser igual a P Nu, velho vai ser igual a P antigo. Agora que temos o novo e o antigo conjunto, nossa mudança será igual ao novo menos o antigo, acho que é a menos que eu o faça ao contrário Ok, então se o valor antigo for 30 e o novo valor for 20, a alteração será menos dez, que é o que queremos aqui. Então, sim, novo menos antigo. Então, basicamente, o que estamos fazendo aqui é passar esses quatro parâmetros para o sinal como um objeto de dados St alterado. E então, no receptor de sinal, a função de retorno de chamada, podemos acessar tudo dentro de St alterado para teta apenas fazendo St changed data dot object, dot new dot dot CAGE E talvez não precisemos de tudo isso, mas temos tudo acessível. Além disso, se adicionarmos outra coisa aqui, como var Cookie, que é um tubo de textura ou algo parecido , não precisaremos adicionar isso como um parâmetro extra. Está contido nesta classe. Assim, você pode modificar esse objeto sem precisar alterar seus retornos de chamada ou o parâmetro do sinal de envio porque está enviando apenas um objeto Espero que isso faça sentido. É mais fácil modificar à medida que você avança. De qualquer forma, nossos dados estatísticos foram alterados. Então, se voltarmos ao nosso script de controlador de estatísticas, agora podemos criar nossos sinais Portanto, Max HP alterado fará com que os dados da estatística sejam alterados Ok, e então nós apenas sinalizamos para o outro sinal, HP alterou os dados, as estatísticas alteraram os dados, a experiência do sinal mudou Dados estatísticos alterados. Agora, a razão pela qual eu colocaria um sinal para cada um deles é porque, no script de recebimento, podemos escolher com quais estatísticas realmente nos importamos. Então, por exemplo, a tela EXP aqui só se preocupa com a mudança de experiência Então, vamos nos conectar apenas ao sinal de mudança de experiência e talvez também a um sinal de mudança de nível para atualizar o rótulo de nível, se ele estiver na mesma área de exibição. Então, temos esses sinais. Só precisamos emiti-las. Então, o que eu estava fazendo antes com, tipo, o configurador HP aqui, se você vai apenas emitir o valor alterado, acho que é aceitável o uso de um conjunto, então emitimos que o valor mudou e apenas o tornamos uma propriedade observável tornamos uma propriedade Então, vou dizer aqui que, sempre que configurarmos o HP, diremos que o HP mudou de ponto em HP. Agora, se estamos configurando para HP 100 quando já está 100 repetidamente, talvez queiramos pular essa emissão de sinal, para que possamos dizer que se a HP é igual ao valor , retornaremos porque não precisamos atualizar ao vivo Não precisamos atualizar o HP porque é o mesmo valor. Então, seguindo esse padrão, vou basicamente fazer a mesma coisa com o MAX HP. Então, vamos fazer cólon. Próxima linha, defina o valor. Se Mx HP for igual ao valor, retornaremos. Caso contrário, Max HP é igual a valor, e emitimos Max HP alterado Ah, mas aqui embaixo, esqueci que esse não é apenas o valor da HP aqui, mas na verdade precisamos criar o objeto de dados alterado por estatísticas Os dados são iguais aos dados alterados por estatísticas, ponto novo. E vamos passar essa referência de objeto aqui para o controlador de estatísticas Então, objete, e então fazemos o novo valor de HP e o valor antigo, que precisamos obter primeiro. Então, antes de definirmos o novo valor em HP, logo antes disso, fazemos var Old é igual a HP, e agora colocamos o antigo aqui e passamos os dados para a emissão do sinal Então, a HP mudou o ponto MMI com os dados, e isso é tudo o que precisamos fazer E agora ele terá essas quatro propriedades de dados dentro desse objeto em vez de apenas uma, mas ainda parece super limpo porque estamos enviando apenas um objeto. Ok, agora no MX HP, queremos fazer isso de novo. Então, vamos dizer que var Old é igual a Max HP, e então vamos fazer far data equals stat changed data dot u. acontece com o objeto, o Max hP e o antigo, e então emitimos o sinal HP alterado com os dados Ok, então seguindo o mesmo padrão, mais uma vez, aqui na experiência, dois pontos definidos, ainda podemos evitar se a experiência for do mesmo valor, por precaução Então, se experiência é igual a valor, nós retornamos. Caso contrário, obtemos o antigo igual à experiência e, em seguida, a experiência é igual E então os dados de Vara são iguais ao ponto de dados estatísticos alterados w. A experiência do objeto é antiga, e emitimos a experiência alterada com os dados. Está bem? E eu poderia acrescentar isso. Oh, sim, ok, esqueci o D lá na parte superior do sinal Controle o STA, e isso deve ser bom. 39. L38 Criação de scripts para exibições dinâmicas de HP e EXP para a interface do usuário: Então, temos a configuração do sinal, e temos nosso contexto aqui e a interface do jogador, que nos permitirá pegar esses sinais do bloco de estatísticas. Mas, na verdade, não precisamos fazer isso diretamente na interface do jogador. Precisamos fazer isso na tela HP e na tela EXP. Então, eu quero criar scripts para a tela HP e a tela EXP aqui embaixo Então, clique com o botão direito do mouse na tela HP, anexe um script e podemos colocá-lo na interface do usuário, então hp display dot GD. Ótimo. Podemos simplesmente fazer isso se estender a partir do contêiner. Nós realmente não nos importamos com o tipo de contêiner porque você pode criar uma tela usando outros tipos. Talvez você exiba seu HB verticalmente em vez Portanto, você pode usar uma classe base diferente, como contêiner em vez de contêiner HBox, e ainda pode criar o nó real no contêiner HBox Então, manter as coisas flexíveis é a ideia aqui. E eu vou dizer o nome da classe HP Display. Ok, então em nossa tela HP, precisamos de uma referência às estatísticas do controlador do jogador. Poderíamos exportar o contexto do player e, em seguida, obtê-lo diretamente aqui para cada uma das telas. No entanto, se configurarmos coisas dessa forma, para cada um dos componentes da subinterface do usuário, se cada um deles tiver uma propriedade de exportação que você precisa definir, fica muito difícil arrastá-la para a cena para reutilizá-la a cena para reutilizá-la , porque então você precisa clicar com o botão direito do mouse nela e torná-la editável e certificar-se de atribuir todas as propriedades individuais, clicar com o botão direito do mouse nela e torná-la editável e certificar-se como o contexto do como Para cada nó da subinterface do usuário diretamente. Portanto, outra opção, que pode ser preferível, é fazer com que a interface do usuário raiz injete o contexto do jogador ou o que é relevante a partir dele, o controlador de estatísticas, em cada um dos nós da subinterface do E então você só precisa se certificar de que a interface do player conheça seus subcomponentes, como a tela HP e a tela EXP. Mas então você deixa a interface do jogador lidar com o trabalho pesado. Então, como isso seria no contexto de nossa tela HP, seria que precisaríamos de nosso controlador de estatísticas local Então, se nosso sublinhado iniciar o controlador de estatísticas. Então, tornamos isso local, certo? Em seguida, criaremos uma função setter para que possamos definir o controlador de estatísticas a partir da interface do player Então, digamos que as estatísticas do conjunto de funções, e isso exigirá um controlador de estatísticas de sublinhado P. Qual é o tipo de controlador estatístico. Vou voltar vazio. Eu coloquei o sublinhado P como parâmetro para que fique bem claro que essa variável é um parâmetro da função Caso você tenha outro controlador de estatísticas aqui, não haverá confusão entre nossa referência local ao controlador de estatísticas e nosso escopo de função, P underscore stat controller P underscore Então, vamos usar essa função de definir estatísticas para fazer isso. Então, as estatísticas de sublinhado são iguais ao controlador de estatísticas de sublinhado P. Ok, então temos nosso método de estatísticas definidas. Ele atribui as estatísticas às estatísticas, que são privadas aqui por causa do sublinhado mouse, esse é um script GD, então não é verdadeiramente privado Está apenas marcado que você não deve acessá-lo de fora da classe, mas tecnicamente você ainda pode Então, temos nosso definidor de estatísticas aqui. Queremos nos conectar ao sinal agora. Então essa é a tela da HP. E eu quero dizer que as estatísticas Hp mudaram dot Connect, e vamos dizer que no HP mudou E também podemos dizer estatísticas de sublinhado mxhpHanged E isso pode ser apenas um sublinhado em Max HP alterado. Então, tecnicamente, os dois sinais têm os mesmos parâmetros, então poderíamos usar apenas uma função de retorno de chamada, se quiséssemos Mas, para mantê-lo flexível, talvez haja algum código que queiramos fazer de forma diferente, dependendo se é MaxHP ou se o HP foi alterado, terei apenas dois retornos de chamada aqui, então sublinhado da função No Max, o HP mudou, o que terá os dados P, a estatística mudou os dados, essa reviravolta E o que queremos fazer é atualizar a LUI. Então, vou apenas criar uma função de atualização aqui e, em seguida, faremos a mesma coisa com o HP Changed Então, podemos simplesmente copiar isso aqui e depois remover o bit Max. Portanto, exclua quatro vezes. Ok, é isso. Agora precisamos de uma função de atualização. Então, vamos dizer atualização da função. E o que queremos fazer na tela da HP? Sempre que o HP muda? Queremos atualizar o valor do controle deslizante e atualizar o rótulo do texto Então, queremos basicamente obter a porcentagem saudável por porcentagem de saúde, e isso será uma flutuação igual a, digamos, sublinhado estatísticas ponto HP, sublinhado estatísticas ponto HP, dividido por sublinhado estatísticas ponto Ok, então com a porcentagem de saúde, podemos atribuir isso à barra de progresso da textura. Então você pode ver agora que precisamos de uma referência para a barra de textura aqui embaixo. Então, a única vez que vamos configurar a referência à barra de textura é como a primeira vez que estamos criando essa cena de exibição da HP. Talvez salvemos isso em uma cena separada em nosso projeto, e a cena principal que realmente colocamos no mundo é a cena da interface do jogador. Mas acho perfeitamente razoável exportar a barra de textura e o rótulo aqui. Também há outras maneiras de pegá-los. Mas esse é o método que vou usar. Então, direi que em export var progress é uma barra de progresso de textura. E então, na exportação, var label é um rótulo. Então, quando estamos nos atualizando, podemos pegar o progresso e usar o rótulo, e diremos que o valor do ponto de progresso é igual Então, deixe-me ver. Isso deve estar em uma escala de 0 a 100 E esse cálculo na verdade vai te dar 0,021 0,0 Então, queremos multiplicar isso por 100 para obter uma porcentagem real multiplicada por 100 E não tenho certeza sobre a ordem das operações aqui. Então, vou apenas embrulhar essa parte para garantir que ela seja executada antes disso com certeza Ok, e então o valor do progresso será nossa porcentagem de saúde de 0 a 100 como flutuador Em seguida, precisamos definir o valor do texto no rótulo. Portanto, o texto do ponto do rótulo será igual à string. Poderíamos simplesmente dizer entre aspas HP, porcentagens, saindo com uma barra para frente e porcentagens, e então substituirmos esses valores por um sinal de porcentagem e os passamos em uma Então, os valores que vamos usar serão o HP atual e o MX HP Então, em outras palavras, sublinhado estatísticas ponto HP e sublinhado começa ponto MAX Então, se você quiser que isso seja personalizável, podemos cortar isso com o Control X e substituí-lo por algo como um modelo de texto de saúde Então, aqui no topo, poderíamos dizer que na barra de exportação o modelo de texto Health será igual a, e então o Control V cole isso. Isso ainda tem esses percentuais como símbolos para substituição. Portanto, ainda fazemos a porcentagem do modelo de texto de saúde e, em seguida, a matriz dos dois valores em ordem, que é sublinhado, estatísticas, ponto HP, e, em seguida, sublinhado, estatísticas, ponto máximo Ok, então isso atualizará a barra e atualizaremos o texto. Então, também queremos chamar isso sempre que definirmos as estatísticas. Então, vou dizer que atualize aqui para garantir que, depois de definirmos as estatísticas, também atualizemos imediatamente esse texto Precisamos de dois pontos aqui para finalizar essa função, e isso é muito bom Agora, no lado direito do script, precisamos atribuir o progresso e o rótulo. Então, atribua a barra de progresso da textura e atribua o rótulo. Certifique-se de selecionar os que estão abaixo da barra HP. Agora, isso vai ser bom para a tela da HP. Quase queremos o mesmo script para a exibição EXP, mas há algumas diferenças Então eu vou controlar A, Control C para copiar tudo neste script. Vamos até a tela EXP. Clique com o botão direito, anexe o script. Exp display dot gD parece bom para mim. entanto, alteraremos o tipo de herança aqui para contêiner e, em seguida, basta selecionar tudo e substituí-lo por um Control V colando-o Agora precisamos alterar o nome da classe para exibição EXP. Nosso modelo HealthText. Vamos selecionar esse Control R para substituí-lo pelo modelo de texto EXP Neste modelo de texto de saúde, selecione o texto. Você pode clicar duas vezes nele para selecionar tudo. E então faça o Control R. Aqui embaixo, vamos substituir o modelo de texto Health pelo modelo de texto EXP, substituir tudo e, em seguida, queremos mudar esse HP aqui para EXP como nosso modelo padrão A última coisa que precisamos fazer é alterar a conexão do sinal para que a experiência seja alterada. Podemos nos livrar completamente do Max HP alterado e, em seguida, substituir o nome dessa função aqui mesmo na alteração de HP para que você possa selecioná-la, Control R, e aqui embaixo, queremos substituí-lo na EXP alterada ou experiência alterada, o que fizer sentido para você Vamos substituir isso. Livre-se dos dados alterados do Max HP aqui para finalizar esta parte. Ainda não vamos atualizar a barra de progresso, então vou comentá-las. Então, por enquanto, ampliaremos aqui e eu substituirei o modelo de texto de experiência experiência de pontos com sublinhados, e também colocarei a experiência aqui novamente. Então, dirá como um em um ou dois em dois, mas pelo menos podemos ver isso funcionando. Agora, no canto superior direito, certifique-se de atribuir o progresso. Para a barra de progresso da textura, o rótulo para o rótulo. Então, precisamos apenas da tela HP e da tela EXP para chamar a função de estatísticas definidas a partir da interface do jogador Então, dentro do script de interface do player, vamos exibir ExportVRHP do tipo HP Display em Export var EXP display of type EXP display E então a função underscore está pronta, vamos chamar hp display dot set Stats para contextualizar dot play dot stats, e precisamos obter isso duas vezes para que possamos até mesmo dizer var stats do stat Controller, então definimos isso como igual a esse bit Então eu vou cortar isso, ir até aqui, sinal de igual, colar. Então, definimos estatísticas nas estatísticas. Fazemos a mesma coisa com EXP display XP display dot set Stats E depois fazemos estatísticas. A última coisa que precisamos é atribuir a tela HP a tela EXP e o inspetor para que tenhamos essa referência Então clique na interface do jogador, vá para o canto superior direito e atribua a tela HP. E atribua a exibição EXP. Agora, na verdade, a tela HP e a tela EXP podem e provavelmente devem ser suas próprias cenas independentes, das quais instanciamos uma cópia na interface do usuário do player Então, vou clicar com o botão direito do mouse na tela HP e salvar a ramificação como uma cena dentro da nossa interface de usuário e, em seguida, clicar com o botão direito na tela EXP e fazer a mesma coisa Salve a ramificação de uma cena dentro da interface do usuário. Então, agora podemos entrar neles e personalizar individualmente essas pequenas telas conforme necessário no contexto de nossa maior interface de usuário de jogador. Então, temos cenas dentro de cenas e, em seguida, pegamos a cena da interface do jogador e a colocamos no mundo do jogo, que está invisível agora porque a interface do Canvas foi atingida. Mas sim, aí está. E se estivermos jogando, veremos se alguma coisa está conectada corretamente. Ok, então defina as estatísticas e a exibição do HP é nula porque esqueci de atribuí-las no inspetor Você pode ver aqui que eles são nulos quando prontos, o que significa que esqueci isso na exportação Além disso, como isso é uma verificação, não precisamos de nenhuma afirmação porque está implícito aqui que isso é necessário Então entre na cena do jogador, clique na interface do jogador, atribua a tela HP e a tela EXP De qualquer forma, agora podemos jogar e vamos testá-lo novamente. Portanto, temos dez de 100 HP. Se bem me lembro de ver as estatísticas, nosso HP máximo era 100 e nosso HP básico era dez, o que obviamente é atingido aqui. Você pode ver as atualizações da HP para zero. A barra de progresso do EXP ainda não está funcionando porque precisamos configurar nossos requisitos de experiência de nível E, o que criará, tipo, toda uma hierarquia de subida de nível Mas vamos tentar rapidamente, configurando o HP para 50 em nosso player. Então, vou para a cena do nosso jogador e depois vou dar uma olhada no controle de estatísticas aqui E vamos definir o HP para 50. Deixe-me ver. Se eu fizer isso ali mesmo, posso voltar ao jogo? Não, porque os jogadores já foram removidos, eu acho. Mas ao clicar em play, devemos ver a atualização da barra de HP aqui com o valor de progresso correto, mas isso não acontece. Ele mostra o valor correto da HP, mas temos que consertar a tela da HP bem rápido. Ok, então na tela da HP, deixe-me ver o que estava acontecendo aqui. O valor do progresso é igual à porcentagem de saúde. Deixe-me definir um ponto de interrupção aqui, clicarei em Play e veremos o que realmente está configurando isso para que a porcentagem de saúde seja 0,0. Ah, certo, porque estou dividindo com números inteiros. Então, quando dividimos por dois inteiros, obteremos um inteiro, que vai automaticamente para o piso zero. Mas não é isso que queremos. Na verdade, queremos que ele retorne um fluxo. Então, o que poderíamos fazer como uma solução rápida aqui é simplesmente flutuar no Mx HP Então, agora isso vai ser um número inteiro dividido por um flutuador, que retornará um flutuador que retornará Se clicarmos em play, veremos o valor certo ir para lá. Então, agora podemos ver uma porcentagem de saúde de 50. Se clicarmos em play, a barra está aparecendo corretamente. Menos a compensação do valor . Então, deixe-me ver. Eu compensei o valor lá, monitor HP? Temos a barra de progresso da textura e, por algum motivo, é até 00 aqui, mas quero que seja menos 20 para que, quando o valor for 50, apareça corretamente no meio. Você pode ver ali mesmo que isso é como quatro de 8 barras. E o valor aqui é 50. Devo ter desativado isso em algum momento, mas o tipo de solução idiota para isso é fazer com que o valor mínimo fique mais para a esquerda para que 50 acabe no Porque se isso for zero aqui, então 50 na verdade acaba como, tipo, a terceira barra. Veja, eu me certifico de que seu valor masculino seja negativo 20, e isso deve funcionar para a tela HP. Ok, então no teste final aqui, clicamos na barra de progresso do jogo, configurada para 50. Eu posso desfazer esse ponto de interrupção, apertar play. E podemos ver que nossa barra de progresso de saúde está corretamente no meio, ali mesmo. Nosso HP está nos mostrando 50 de 50. Vamos ser atingidos. Você pode ver nossa queda de HP A interface reflete isso imediatamente, incluindo a barra de progresso. Portanto, todos os nossos sinais estão se conectando corretamente. Estamos definindo a experiência e só precisamos adicionar nossas definições de aumento de nível para que possamos aumentar o nível de nosso personagem Antes de terminarmos completamente o vídeo em nossa função de estatísticas definidas, há uma falha aqui: se algum dia redefinirmos as estatísticas com estatísticas definidas, e uma já estiver definida aqui, acabaremos com sinais duplicados Então, queremos dizer aqui que, se as estatísticas de sublinhado não forem nulas antes de chamarmos set Stats, queremos nos desconectar dos sinais, para que possamos dizer sublinhado stats dot mxhPhanged dot O sublinhado no MAX HP foi alterado. E a mesma coisa para o HP normal. Então, nós apenas copiamos isso e fazemos o SATS. A HP mudou, e depois a HP mudou Isso é mais do que apenas torná-lo robusto. Nunca pretendo configurar o controlador SATS para algo diferente, mas caso você o faça, isso garantirá que não cause um bug horrível em que você tenha dois sinais conectados a dois controladores de estatísticas diferentes, mas em mas em Agora, faça a mesma coisa no EXP também Então, se você olhar a tela EXP, vou colar isso e mudar o nome do sinal Então, a experiência do sats mudou e, em seguida, a EXP mudou aqui. Ok, então é assim que deve ser. Sublinhe que a experiência do SATs mudou desconexão na Ok, então isso deve ser bom se você já trocou o controlador SATS Só queria mostrar que um pouco mais completo. 40. L39 Depurando e otimizando scripts de UI e Pickup: Eu queria esclarecer alguns avisos e erros. Estou entrando no console com o projeto até agora. Portanto, se você estiver copiando o código palavra por palavra, talvez tenha se deparado com esses mesmos problemas. Portanto, escolha dois D onde diz que você não pode usar monitorável igual a falso, normalmente porque está bloqueado e você precisa esperar pela configuração não pode usar monitorável igual a falso, normalmente porque está bloqueado e você precisa esperar pela Então, se você clicar duas vezes nisso, mostrará que, na função de remoção, eu estava tentando definir monitorável como falso Bem, na verdade, vou remover o que é monitorável igual a falso aqui, porque quando você libera o Qu, ele é removido no final do quadro atual Quando você chama set deferred, ele é removido no final do quadro atual Portanto, torná-lo não monitorável ao mesmo tempo em que você o libera não vai realmente ajudar em nada O objetivo era fazer com que, se dois objetos tentassem pegá-lo ao mesmo tempo, ele não pegasse duas vezes. No entanto, o que podemos fazer se você quiser estar mais seguro. No entanto, se você quiser ser ainda mais seguro e pegar dois D, vamos escolher entre eles. E esse será um booleano definido como falso por padrão. Então, estou apenas insinuando que é um booleano lá. Quero dizer, se você quiser declarar isso com certeza, então você pode fazer isso. Então, isso é escolhido. E se tentarmos entender quando isso é verdade, então vamos permitir. Caso contrário, retornaremos false. Então, o que vou fazer com o Tr take é fazer com que ele realmente proteja, e então teremos uma função de captura separada, que será o que os captadores realmente implementarão, como a função virtual, o que eles fazem atualmente Então eu quero fazer a função, sublinhar T, e isso não vai retornar nada, então esse é um tipo de retorno de vazio E vou pegar esse erro de push e trazê-lo aqui. Então, vou voltar à verdade aqui agora. Vou mudar isso para sublinhado T. Então, chamamos a função virtual e, em seguida, vamos nos proteger contra voltar aqui pela segunda vez Então, vamos dizer, eu escolhi, retorne falso. Ok, então aí está nosso guarda. Caso contrário, chegaremos aqui. Depois de tirarmos, escolhemos é igual a verdadeiro. E estou colocando isso aqui para que não precisemos nos preocupar com esse booleano e com as classes herdadas Só precisamos nos preocupar implementar a função take. Então eu acho que essa é uma configuração melhor. Funcionará bem com o Ir Quarter e, desde que definamos a opção como verdadeira após a ligação temos certeza de que ela não atenderá pela segunda vez porque temos esse guarda aqui. Então, agora só precisamos atualizar nossos outros scripts de coleta. Então, pesquise e pegue. Acho que só temos captador EXP até agora Então, vou clicar duas vezes nisso. Vamos renomear isso para sublinhar Take the return type is E em vez de retornar false aqui, se as estatísticas forem nulas, enviaremos um erro Então, erro de push. A porcentagem não tem controlador de estatísticas. Essa será a meta de porcentagem P. Então, substituímos isso por um nome de nó. E então não voltamos ao fundo. Nós apenas chamamos de remove. E precisamos ter certeza de que combinamos com a assinatura dos pais. Então, provavelmente preciso passar o alvo P para o script pai. Ok, então vamos subir. E sim, queremos ultrapassar a meta P. Então, como alvo P, removeremos o sublinhado porque , na verdade, o estamos usando agora E aqui sublinhamos que o alvo P é um nó dois D. Agora, isso deve eliminar os erros em nosso EXP Pickup dois D. E só para verificar, entraremos Ok, então os outros avisos, vamos ao que interessa. Na maioria dos casos, esses são apenas parâmetros não utilizados. Então, no caso de algo como pegar dois D, você vê que o alvo P não é usado, então você só quer marcá-lo com sublinhado para que seja marcado como Vamos para o próximo aqui. O tamanho da câmera nunca foi usado. Portanto, o tamanho da câmera foi usado , na verdade, para criar o reto da câmera. Então, na verdade, não é necessário aqui porque nesta função de cálculo final de geração, usamos para o sistema de geração. O reto da câmera é criado e, em seguida, o tamanho é retirado dele Então, podemos realmente remover tamanho da câmera como parâmetro e cortar isso. E então, quando chamamos isso aqui, basta remover o tamanho da câmera como parâmetro e simplificá-lo para três parâmetros. Então, esse seria um bom caso em que esse aviso realmente nos ajudasse. E então, a seguir, se você tiver uma atualização que não usa o Delta, o que seria o caso se você movesse e deslizasse porque mover e deslizar não precisa fazer o Delta, você define a velocidade e, em seguida, move e desliza automaticamente as alças com o Delta Então, destacamos o Delta e pronto. E esse script de drop, o nome drop aqui está sombreando o nome da função Então, poderíamos mudar o nome aqui para algo como drop instance. E então, sempre que usamos drop under it, como aqui, dizemos drop instance em vez disso. Você só quer ter certeza de que se usar uma variável localmente, não tenha essa variável declarada fora do escopo na base da classe, como as variáveis locais. E você também não quer que ele tenha o mesmo nome de uma função. Então, em cada um desses sinais de alteração de estatísticas, os retornos de chamada, eu estava apenas atualizando sempre que o valor mudava e, na verdade, não precisava usar os dados P diretamente para essas funções Então, eu apenas sublinharia os dois mais uma vez no script de exibição do EXP. Clique aqui e sublinhe isso, e isso deve eliminar todos os avisos e erros atuais E eu vou clicar em Play. Ok, sem erros para. 41. Sistema de classificação P40 com experiência e progressão de estatísticas: Saúde e experiência Agora, precisamos adicionar algum tipo de mecânica de nivelamento e precisamos ter uma estatística de nivelamento em nosso controlador de estatísticas para gerenciar o aumento de nível de nosso jogador e possivelmente de outros personagens, mas Então, vamos entrar no controlador de etapas e vou adicionar uma nova variável aqui. Diremos que será um número inteiro igual a zero e teremos uma configuração semelhante à experiência aqui embaixo, onde teremos apenas um onde teremos apenas saturação em que diremos que o nível I é igual ao valor que retornaremos, caso contrário, repetiremos o mesmo padrão emitindo o sinal de alteração de nível para que possamos responder a isso em nossa interface do usuário nível I é igual ao valor que retornaremos, caso contrário, repetiremos o mesmo padrão emitindo o sinal de alteração de nível para que possamos responder Então, diremos que var old é igual ao nível e diremos que o nível é igual Diremos que var data é igual a stat changed data dot u object level old e emitiremos um sinal de alteração de nível Com os dados. Agora, precisamos criar esse sinal, é claro, então o nível de cópia mudou na parte superior. Vamos criar dados alterados no nível do sinal, dados alterados nas estatísticas Então, agora podemos assinar isso, se precisarmos. Agora podemos implementar totalmente a adição de experiência. Então, sempre que adicionamos experiência, também queremos verificar se estamos prontos para o próximo nível. Eu coloquei isso aqui, em vez definir a experiência, porque não quero muitos efeitos colaterais aleatórios ao definir a experiência. Por isso, quero chamar explicitamente o método de experiência publicitária, que aumenta de nível se o limite Ok, então para fazer isso, precisaremos criar um objeto de definição de nível. Então, vamos criar um novo script para isso. Tudo vai entrar, digamos, nos personagens. Clique com o botão direito aqui, faça um novo script, e nós o chamaremos de definição de nível. Então, ponto de definição de nível gD. Vai se estender a partir do recurso, criar. Clique duas vezes para abri-lo e forneceremos uma definição do nível do nome da classe. Isso ampliará os recursos e definirá um aumento de nível para um personagem. Então, o que precisamos aqui será o limite de experiência Então, na Export VR, diremos que é necessária experiência. E isso será um número inteiro. Poderíamos usar como padrão algo como dez. E provavelmente também queremos algumas estatísticas para subir de nível. Então, por enquanto, vamos começar com a HP e simplificar, mas você criaria estatísticas extras aqui mais tarde, à medida que descobrisse que elas se tornaram mecânicas Então, em Export var HP, diremos que é um número inteiro, padronizado para dez E podemos dizer que esse é o bônus de HP por subir de nível. Então você atinge esse nível, seu personagem recebe tanto HP. Agora, como aplicamos nossas mudanças de estatísticas ao personagem? Você poderia fazer isso um de cada vez manualmente, mas uma maneira mais inteligente seria criar um método para fazer isso por você Então, digamos que a função se aplique, e vamos aplicar isso em um controlador de estatísticas, digamos. Então, as estatísticas P de um controlador de estatísticas. Então retornaremos vazios com isso. Então, queremos basicamente atualizar os conjuntos. Portanto, P stats dot HP plus é igual à quantidade de HP. E antes disso, também queremos aumentar o MX HP. Então p stats dot MX HP plus é igual a HP. É importante que você faça o MAX HP antes do HP porque o HP atual está limitado ao MAX HP. Portanto, se um personagem com saúde completa aumentar seu HP em dez, na verdade ele não ganhará a saúde a menos que o HP MÁXIMO seja atualizado primeiro. É muito importante fazer o pedido lá. E essa pode ser nossa definição básica de nível por enquanto. Portanto, no controle de estatísticas, seria um lugar decente para definir nossas definições de nível Então, vou dizer que na exportação, aumente as definições de VR. E isso é uma matriz de definição de nível. Ok, então para verificar a subida de nível, precisamos obter o próximo nível na sequência. Então, vamos criar uma função para obter nosso próximo nível, se houver um. Então, aqui embaixo, digamos que função, sublinhado, chegue ao próximo nível O que retornará uma definição de nível ou nula. E isso retornará as definições de nível superior do Git, e chegaremos ao nível do índice Então, a razão pela qual estamos chegando ao nível do índice é porque o nível é, na verdade, o segundo lugar na matriz. Então, se nosso personagem está no nível um, estamos atualmente no índice zero e queremos ver o índice mais um, que é o nível porque o nível começa em um. Ok, então, para lidar com nossa subida de nível de experiência adicional, primeiro precisamos obter a definição do próximo nível para o próximo nível Então, como o nível mais um, precisamos colocar essa definição de nível no topo. Então, vamos ao Export, não de certa forma, mas na verdade um dicionário aqui. Então, em Exportar definições de nível de VR, diremos. E isso será um dicionário de números inteiros que são atribuídos à definição de nível Portanto, o número inteiro é o nível que estamos tentando alcançar, e a definição do nível as mudanças de estatísticas que ocorreriam se existissem Portanto, antes de subirmos de nível ou tentarmos subir de nível, precisamos primeiro ver se há realmente um nível definido. Então, na parte inferior, criaremos outra função de função privada underscore get next level, e isso retornará uma definição de nível ou nula Então, retornaremos nossas definições de nível dot GET no nível mais um. Nosso nível atual mais um, queremos obter isso e queremos retornar nulo Se não conseguirmos encontrá-lo. Então, se retornarmos null , pularemos a subida de nível Então, nessa experiência, vamos fazer VR. A seguir será uma definição de nível igual à obtenção do próximo nível. Então, se o próximo for nulo, nós simplesmente retornaremos ou você pode até mesmo enviar um aviso Na verdade, sim, vamos dar um aviso. personagem não pode subir de nível até uma porcentagem mais um porque esse nível não tem uma definição definida. Então, poderíamos dizer uma sequência de níveis mais um aqui no final e finalizá-la com outros parênteses. Ok, isso vai funcionar. Então, pegamos o nível mais um. Estamos tentando subir de nível para o nível dois se estivermos no nível um, e notamos que não podemos subir de nível porque isso não está definido. Então, talvez você queira ter isso como um aviso ou, se tiver certeza de que não quer, pode simplesmente comentar ou remover. Vou deixar isso aí por enquanto para que possamos pelo menos ver quando falhamos em definir uma definição de nível. Então, o próximo nível é nulo, então se o próximo for nulo, retornaremos porque não podemos subir de nível Não há um próximo nível definido. Então, simplesmente pulamos completamente. E então queremos verificar se o requisito de experiência do próximo nível é menor ou igual à nossa experiência atual. Então, podemos colocar isso como parte de uma função de três níveis. Então, sublinhe três níveis acima, e diremos no próximo Então, viemos até aqui e teremos nossa função. Sublinhado. Tente subir de nível. Sublinhe porque é privado e passamos para a definição do próximo nível Ou na verdade, você sabe, eu sinto que isso deveria estar contido nessa função, na verdade. Então, isso retornará um booleano, e teremos isso aqui Então, acabamos de obter o próximo nível dentro dessa definição. E então não precisamos passar um parâmetro. Nós apenas tentamos subir de nível depois de adicionar XP, certo? É exatamente assim. Então, se não conseguirmos subir de nível, retornamos false. E então queremos verificar se a experiência é maior ou igual à experiência necessária no próximo ponto. Se for esse o caso , subiríamos de nível. Mas eu vou reverter isso. Eu vou dizer que se for menos do que a experiência necessária , retornaremos false. Ok, então estamos fora da declaração if novamente. E então, se chegarmos até aqui, passamos pelas verificações de guarda, então podemos dizer que nível mais é igual Subtrairemos a experiência necessária da experiência atual Então, experiência menos é igual ao próximo nível. Oh, desculpe, a seguir, não é necessária experiência. E então aplicaremos as estatísticas do próximo nível às nossas estatísticas atuais. Então, depois de subtrair o XP, aplicamos o próximo ponto a si mesmo porque estamos trabalhando dentro do script do controlador de estatísticas e, em seguida, retornaremos verdadeiro porque subimos de nível com sucesso Agora deixe-me pensar sobre isso. Acho que realmente quero que o nível aumente após a aplicação das estatísticas, dessa forma. Então, se vamos dizer, que um personagem suba de nível e, em seguida damos a ele as opções de recompensas. Então, escolhendo uma atualização na subida de nível, que é uma mecânica básica e como a de nosso sobrevivente, queremos fazer isso depois que as estatísticas básicas se aplicarem, para que a interface ainda seja atualizada basicamente no mesmo quadro, mas pouco antes de subirmos de nível e emitirmos nosso sinal de mudança de nível, fazendo com que a interface reaja e nos mostre Acho que é importante mudar o pedido lá. Ok, então sim, então o nível do sinal de mudança será emitido aqui por causa do configurador E isso é basicamente nossa subida de nível. Se, por algum motivo, você quiser obter a definição do nível atual, isso pode ser útil fora do script. E esse pode até ser útil fora do script. Então, vou pegar o próximo nível, e removeremos o sublinhado para girar , mover esse sublinhado e tentar E vamos adicionar uma função G nível atual. Definição ou talvez apenas esclareça os níveis atuais o suficiente. E então retornaremos a definição do nível. Então, retornaremos as definições de nível dot GIT e queremos retornar o nível ou nulo OK. Portanto, eles podem ser úteis para outros scripts que desejam analisar o que está acontecendo com o controlador de estatísticas Portanto, faz algum sentido torná-los públicos. Ao não ressaltar É por isso. Ok, então temos essa propriedade de estatísticas e podemos subir de nível sempre que nossa EXP aumentar, que deve ser automático, pois essa experiência publicitária será chamada de nossa coleta, nossa coleta de EXP Então, tudo vai fluir bem se estiver funcionando bem Só que agora precisamos ter certeza de que estamos nos conectando à estatística de nível e ao aumento de nível ou ao sinal de alteração de nível, em vez disso E vamos fazer isso dentro da tela EXP. Então, precisamos procurar EXP em um projeto e rolar para baixo, encontrar nossa cena xp display dot TSCn e abri-la Ok, agora que nosso nivelamento deve estar funcionando, precisamos entrar na tela de EXP e garantir que ela mostre quanta EXP precisamos para o Então, vamos entrar aqui. E quando atualizamos, queremos obter o próximo nível de XP Queremos mudar essa parte aqui para o XP máximo das estatísticas, se as estatísticas tiverem um próximo nível que possamos realmente acessar Então você se livra dessa parte e diz que VarnNxt será igual a underscore stats Então, obtemos o próximo nível e, se não houver um próximo nível, diremos que I next é igual a nulo e, em seguida, queremos alterar o texto do ponto do rótulo para ser igual a, digamos, nossa string de nível máximo Ok, então precisamos definir isso aqui na string de nível máximo de exportação var, e isso será igual a algo como o nível máximo em maiúsculas. Ok, senão, vamos definir o texto para nossa EXP, nosso número atual a partir do número do próximo nível Então, confirmamos que next não é null, então podemos substituir esse bit pela experiência next dot, Ned Agora, se eu executar o jogo, provavelmente dirá apenas nível máximo porque não definimos nenhuma definição de nível. Se estivermos no nível MAX , também quero pegar a barra de progresso e definir esse valor como 100. Então, agora, se rodarmos o jogo, atualmente, isso nos dará um erro porque eu não configurei o progresso, então vamos fazer isso. Então, em nossa tela XB, vá para a direita e atribua a barra de progresso Ok, agora podemos correr e devemos ver uma barra de progresso completa. Estamos no nível MAX. Ok, então pegar o XB não importa mais Ainda tenho uma boa experiência, mas ela nunca mais subirá de nível. Porque as definições de nível são atribuídas no editor, não durante o jogo. Embora você pudesse fazer isso, mas isso seria muito estranho, certo? Como definir no final do jogo que você pode subir de nível até agora o nível 31, onde antes 30 era o limite, não, isso é algo que você faz no editor. 99,99% do tempo. Portanto, temos o valor do progresso sendo definido aqui. Queremos obter uma porcentagem entre nossa experiência e a próxima experiência necessária e, em seguida, atualizaremos o valor do progresso aqui para quando pudermos subir de nível. Portanto, nosso progresso está aumentando e definiremos isso como igual à experiência necessária no próximo ponto dividida pela experiência de pontos nas estatísticas de sublinhado Agora lembre-se de que estamos dividindo um inteiro por um inteiro, mas na verdade queremos que seja um flutuante Então, precisamos pegar um desses e lançá-lo como um flutuador. Então diga flutuar. E então, em stats dot experience, terminamos de colocá-la entre parênteses Então fazemos isso, e isso agora deve nos dar algo entre 0,0 e 1,0. Mas isso precisa ser basicamente convertido em uma porcentagem porque nossa barra de progresso por padrão, tem um valor máximo de 100, então estamos analisando porcentagens Ou isso, você precisa reduzir o valor máximo para um. Ambos são realmente válidos. Então, aqui podemos simplesmente colocar outros parênteses e multiplicar por 100, e isso deve nos dar nosso Então, ainda não vamos chegar a isso porque precisamos definir algumas definições de subida de nível. Então, vamos até o player e clicaremos no controlador de estatísticas Temos nossas definições de nível aqui. Assim, podemos adicionar alguns valores-chave do dicionário. Queremos que o próximo nível de dois seja definido aqui. Então, adicione dois e uma nova definição de nível. Dentro daqui, podemos dizer que o XB precisava de dez HP e dez. Isso é bom para começar. Adicione o par de valores-chave. É importante que você se lembre de bater nisso. Caso contrário, não estará no dicionário. Portanto, temos nosso dicionário com uma chave no nível dois e uma definição de nível para aumentar o nível de nosso personagem. Ok, um último pequeno ajuste que precisamos fazer é garantir que nosso jogador passe para o nível um. Então, vamos ao controlador de estatísticas e onde temos o nível Precisamos ter certeza de que é um. Dessa forma, quando verificarmos o nível mais um dos dois, encontraremos essa definição de nível e ela deverá ser exibida corretamente na interface do usuário. Então, vamos clicar em Play e teremos nosso XB necessário aqui. A barra de progresso não foi atualizada, mas vamos ver quando obtemos uma EXP, ela aumenta e aparece em dez E sim, erro simples. Esqueci de atribuir o progresso ao valor do ponto de progresso Então, talvez realmente faça sentido mudar isso para um nome diferente. Estamos sombreando uma variável. Aposto que se eu verificar os erros aqui, você pode ver que sim, eu sombreei isso com o nome da barra de textura de progresso Então, digamos que percentual nivelado seria um nome muito melhor. E então diremos que o valor do ponto de progresso é igual à porcentagem E agora tenho certeza de que deve funcionar. Vamos jogar. Vá lá. Podemos ver por que o EXP não adorou lá, e agora está dizendo que é um em cada dez Isso é interessante. Então, eu preciso definir um ponto de interrupção aqui para ver o que isso está mostrando E vamos entrar no modo de jogo. E podemos ver que está dizendo 0,0 agora, mas vamos pegar um e obtemos 1.000. Outro erro lógico simples, eu deveria estar fazendo a experiência dividida pela experiência necessária. Então, revertemos isso. Vou pegar a experiência necessária e colocá-la aqui, e depois vou cortar a experiência de pontos de estatísticas e colocá-la aqui à esquerda. Ainda poderíamos fazer a fundição flutuante à direita. Isso é bom. Ok, então vamos jogar mais uma vez. Testar isso? Então, ok, agora está mostrando 0% subindo de nível Pegamos um item. Temos 10% lá, dois, três, mas deve estar indo até o fim. Então, quero verificar o valor da parada de progresso aqui e ver por que isso está ocorrendo. Ok, então aqui temos 40% de subida de nível. Portanto, a porcentagem nivelada está correta. Então, talvez precisemos verificar a interface do usuário fora do jogo. Então, vamos entrar na tela EXP aqui. Vou testar a configuração do valor como zero. Ok, está correto. 100 está correto. Vai até a extrema direita. Digamos que 25, 50, 75. Ok, isso parece correto. Então, vamos levar o valor para zero. Tudo bem, jogue. Vamos testar isso um pouco. Ok, remova o ponto de interrupção. Entre no modo de jogo e vamos fazer um, dois, três. Então isso é 30%? Talvez esteja correto, na verdade. Ok, então obtemos quatro de dez e depois cinco de dez. Ok, sim, estava funcionando bem. Vamos pegar sete de dez. Na verdade, vamos apenas nivelar nosso personagem para provar que ele funciona. Ok, então temos nove de dez, e então temos o esqueleto desovando Podemos obter mais um, dez em dez. Ok, você viu que acabamos de obter dez HP aqui, então passamos para zero em dez para a EXP necessária Então, a parte sobre o próximo nível deveria ser devolver alguma coisa, mas isso não aconteceu. Então, a razão pela qual isso ocorreu é que nossa experiência é definida como zero. Ele emite um sinal, e então nosso nível alterado não se conecta aqui Então, depois que o nível é alterado, ele não é atualizado novamente. Ok, então a solução mais simples é apenas sublinhar que o nível de pontos das estatísticas foi alterado e nos conectamos ao nível alterado para atualizar novamente Então, podemos copiar isso aqui e desconectá-lo. Então, criaremos nossa função de retorno de chamada na função inferior, sublinhando o nível alterado Não vamos usar os dados, então sublinhe os dados P. Os dados foram alterados, retornamos nulos e apenas atualizaremos Ok, dessa forma, depois que a experiência for definida como zero, logo antes de aumentarmos nosso nível, isso atualizará a interface do usuário, mas depois o nível mudará e nós atualizaremos a interface novamente Então, vamos mostrar mais uma vez que tudo está funcionando conforme o esperado. Então, vou ter experiência suficiente para subir de nível aqui. Então, para e depois, cinco, seis, sete, oito, nove. Na verdade, os Skillsins ainda não derrubam nada. Vamos corrigir isso em breve. E depois dez. Ok, agora ele mostra o nível máximo, mas também aumentamos nosso HP. Então, isso atualizou nossa interface do usuário duas vezes. Uma vez quando mudamos nossas estatísticas, diminuindo a experiência e outra vez quando aumentamos nosso nível, que agora mostrará que o próximo nível não existe Então, mostramos o nível máximo em nossa barra de EXP, como seria de esperar. Então, tudo parece estar funcionando. 42. Ladrilho 41 Configurando limites de XP e conexões de sinal para recompensas de aumento de nível: Indique agora onde gostaríamos de adicionar um sistema de atualização semelhante a um desonesto Então, aumentamos o nível de nosso personagem quando ele atinge um determinado limite de XP e, em seguida, selecionamos uma das três opções de como queremos aprimorar nosso personagem E isso é escolhido em uma lista aleatória de opções disponíveis. Então, por uma questão de conveniência, antes de entrarmos nisso, quero alterar o requisito de XP, ajustando o Nível dois para um, que possamos acioná-lo rapidamente Então, se eu for para o player SAN, abriremos o player dot TCN e, em seguida, vamos para o controlador de estatísticas, acredito que foi onde o definimos E a definição do nível, temos o primeiro nível aqui definido em dez XB necessários Vamos mudar isso para um bem rápido. E então talvez eu adicione alguns níveis extras. Então, podemos fazer um nível três aqui como a nova chave e, em seguida, vamos fazer uma nova definição. Vamos fazer com que esse precise de dez. Então, adicionaremos esse par de valores-chave. Você pode adicionar quantas quiser aqui. Então, isso é basicamente uma lista gigante dos níveis que estamos tentando definir aqui à esquerda e a definição de aumento de nível de estatísticas à direita Então, no nível quatro, podemos obter, eu diria, 20 XP necessários, e isso aumenta o HP em dez E continue como quiser. Então, nível cinco, digamos 30 X P e L nível dez. Vou detalhar isso para que eu realmente não precise me preocupar com isso muito mais tarde. Vamos fazer o nível sete. Então, nova definição de nível. Digamos 50 XP, adicionaremos o par de valores-chave, sete, e faremos uma nova definição de nível com 100 XP e adicionaremos isso. E acho que isso deve ser bom principalmente para nosso protótipo com sete níveis diferentes Definitivamente, é o suficiente para testar as coisas. Então, temos essas definições de nível configuradas ao subir de nível, emitirão o sinal de alteração de nível do nosso controlador de estatísticas Então, queremos nos conectar a isso em nossa nova interface de usuário, que nos fornecerá a opção de escolher um dos três itens diferentes ou aumentar o nível dos recursos. E queremos que o jogo seja pausado enquanto nosso jogador faz essa escolha Então, vamos criar uma nova interface de usuário. Vou adicionar um novo nó de controle aqui, aumentar o nível da seleção, acho que é um nome decente, e adicionaremos um novo script a isso. Então, nível U select dotGD. Vamos salvar isso na pasta UI, é claro. Então, faça a interface do usuário e, em seguida, abra e crie. Ok. Além disso, controle para salvar a cena ao lado de onde o script está. Então, isso também está na pasta UI. Vou guardá-lo lá. Ok, agora vamos começar a trabalhar no roteiro. Vou fazer a seleção do nome da classe para cima. Geralmente, a menos que algo seja especificamente um script de uso único que nada mais precise referenciar, quase sempre criarei um nome de classe, se isso não estiver claro até agora um script de uso único que nada mais precise referenciar, quase sempre criarei um nome de classe, . simples fato de ter um nome referenciável facilita muito o trabalho entre scripts Ok, então a maneira mais rápida de obter a referência ao controlador de estatísticas do jogador é você adivinhar. O contexto do jogador. Então, vamos adicionar export var, o contexto, que será o contexto do jogador aqui. Controle S para salvar isso. E então, no inspetor, vamos carregar rapidamente o contexto de um jogador do nosso jogo, e isso basicamente nos dá a referência ao jogador e, portanto, ao controlador de estatísticas Ok, e então, na função underscore ready, queremos ir para o contexto dot player dot stats dot level Chang e nos conectar a ele com um nível de jogador alterado, que será uma nova função que criaremos logo Portanto, sublinhe a função de sublinhado na mudança de nível do jogador. E isso fará com que o objeto de dados de mudança de nível. Então, dados P são o que eles chamam de dados alterados de estatísticas. Portanto, só queremos realmente fornecer a interface do usuário se os níveis realmente subirem. Pode haver algumas circunstâncias estranhas em que decidimos que o nível pode cair no futuro. Então, para evitar isso, diremos que se a alteração do ponto de dados P for maior que zero, sabemos que ela está subindo de nível Ok, então quando o nível muda, só queremos responder a ele subindo de nível, não descendo de nível. Então, vamos dizer que, se a alteração do ponto pdata for menor ou igual a zero, retornaremos aqui porque não é uma condição que queremos tratar Caso contrário, aumentaremos o nível do jogador. Agora, por enquanto, só vou escrever o código para lidar com o aumento de nível, um de cada vez, porque no contexto do jogo atual, essa é a única maneira de isso ser possível Então, vou escrever pelo menos o protótipo do script para lidar com a subida de nível apenas uma vez por vez Se, por algum motivo, você pegou um objeto de 1.000 EXP e isso acionaria um aumento de três ou quatro níveis, essa pode ser uma condição com a qual você queira lidar mais tarde Mas acho que isso é um pouco desnecessário aqui, porque, de qualquer forma, só vamos ganhar um XP por vez Mas para esse script, por enquanto, vamos apenas subir um nível por vez. Então, vamos criar uma função aqui. Vou chamá-lo de seleção inicial. E então essa função, que colocarei acima da seleção inicial da função nos fornecerá três opções. Também mostrará a interface do usuário. Então, podemos começar com uma teleconferência aqui. E então também queremos pausar o jogo para que possamos dizer que colocar três pontos em pausa Ok, então como estamos pausando o jogo aqui, isso significa que ele pausará todos os scripts que estão configurados para estarem ativos somente quando o jogo não estiver pausado, o que é o padrão Então, aqui à direita, em node process, precisamos mudar o modo aqui para, acho que sempre, para que ele sempre possa acionar coisas dentro do jogo, independentemente de estar pausado ou não Porque também queremos poder abrir o script quando o jogo não estiver pausado Portanto, ser capaz de chamar a seleção inicial durante um jogo sem pausa será importante Então, acho que fazer isso sempre faz sentido. Mas definitivamente queremos que ele seja executado enquanto o jogo está pausado Mais tarde, precisaremos entrar aqui e gerar uma lista de recompensas que mostraremos ao jogador. Primeiro, precisaremos configurar um pouco a interface do usuário para isso. E também queremos ter certeza de que isso foi testado até agora para que esteja realmente aparecendo Vamos clicar com o botão direito do mouse na seleção de subida de nível e adicionar alguns componentes de interface de usuário a ela. Então, vou começar com, digamos, um contêiner de painel, e isso nos permitirá vê-lo quando ele aparecer na tela Além disso, clique na interface raiz. E então vamos mudar, vamos ver, layout no canto superior esquerdo e o capset aqui. Então, aí mesmo. Também quero ter certeza de que o mouse não impeça os cliques , mas na verdade vamos ignorá-lo por enquanto Queremos clicar em coisas na interface, como botões para fazer a seleção, mas não queremos que a raiz da interface bloqueie os sinais do mouse e da porta. Então, vamos ver se podemos fazer com que isso apareça ao subir de nível. Vamos até a raiz e adicionarei a seleção de subida de nível. Então suba o nível do sublinhado, e vamos colocá-lo sob a camada de tela Vamos mostrar temporariamente a interface do usuário. Ok. E vamos querer que isso realmente esteja no centro da tela. Então pegue a seleção de subida de nível e vá para o layout no canto superior direito, e vamos centralizá-la aqui. Então, centralize e, se diminuirmos o zoom, teoricamente, isso deveria estar no centro da tela Então, vamos atingir o nível dois e o jogo, e veremos se isso está realmente funcionando. Então, eu vou até aqui. O jogo fez uma pausa. Não vejo isso aparecendo, mas é um bom começo. Então, pelo menos sabemos que está sendo acionado em Lavote. Então, estou pensando que o que pode estar causando o problema aqui é que a escala da camada Canvas está definida como quatro. Vamos fazer esse desse jeito. Ok, e então eu quero um filho para a camada Canvas, que na verdade vou usar para o dimensionamento. Vamos clicar com o botão direito na camada Canvas e adicionar um nó de controle aqui. Então, vou pegar os outros nós e criar a raiz. Portanto, esse nó será a interface do usuário. Ok, também precisaremos assumir o controle da interface do usuário, a raiz aqui que acabei de criar. E vamos pegar as âncoras predefinidas e criar esse retângulo completo Então, agora que isso vai se estender até o tamanho do ponto de vista, queremos garantir que o mouse esteja configurado para ignorar, para que isso não bloqueie os sinais da interface Ok, e então, se tivermos a seleção de subida de nível aqui definida no centro, podemos realmente ver que esse é o verdadeiro centro do ponto de vista Então, aqui está o nó de controle da interface raiz e, em seguida, ele está no centro. Então, se eu clicar em Jogar agora e pegarmos um XP, isso aparecerá no centro, embora estivesse mostrando o bit padrão. Então eu tenho que esconder isso primeiro. E agora vamos clicar em Play. Nós vamos aqui, e você vê que ele aparece, além de pausar o jogo Ok, então esse script está funcionando. Precisamos redimensionar nossa HPUI aqui novamente. Então, na verdade, vou clicar na interface do usuário aqui e vou aumentar sua escala diretamente. Talvez seja o mais apropriado escalar os componentes individuais em vez de aplicar uma escala global a tudo. Então, podemos simplesmente dimensionar nossa seleção de jogos de forma adequada. Portanto, outra vantagem de ter a interface do usuário aqui é que, se quisermos aplicar um tema a tudo abaixo, podemos simplesmente acessar o tema no canto inferior direito e carregar rapidamente o tema do jogo. Então, agora tudo estará usando essa fonte Pixar, mesmo que não a atribuamos diretamente à seleção de subida de nível Então, às vezes você quer controle refinado sobre os temas individuais Se você quiser um tema personalizado para, digamos, a seleção de subida de nível, basta criar um novo aqui embaixo. E acho que nos níveis mais baixos, ele substitui tudo o que está acima Então, você pode basicamente ter uma hierarquia de temas como essa, porque nem tudo precisa substituir todas as propriedades Você pode ter um tema principal e, em seguida, para coisas muito personalizadas, como a aparência de uma barra deslizante, você pode fazer isso como um sub 43. L42 Como aprimorar o layout da UI e o texto animado: Vamos trabalhar na criação de nosso modelo de interface de usuário para a seleção de subida de nível. Então, já temos um contêiner de painel. Acho que devemos esticar isso, então vou puxar o canto inferior direito e movê-lo um pouco maior. Precisaremos de uma interface de usuário muito maior para realmente mostrar nossa seleção. Agora vamos precisar de um cabeçalho. Talvez mostremos um gráfico. Tipo, parabéns. Você subiu de nível algo assim. Então, precisamos de três exibições de colunas. Esses serão contêineres VBox, que mostrarão nossas opções Então, provavelmente será como um texto de título, um ícone, uma descrição e, em seguida, um botão de seleção. E quando o botão de seleção for pressionado, a seleção de subida de nível processará a seleção, aplicará ao jogador, fechará a interface do usuário e retomará o jogo. Então, vamos clicar com o botão direito do mouse em nosso contêiner de painel e adicionarei um contêiner de margem como próximo nível, adicionarei um nó filho. Então, estamos procurando um contêiner de margem. E então, nas substituições de tema à direita, vou pegar essas margens e definir cada uma delas em cinco pixels por enquanto Isso só fará com que pareça um pouco mais bonito , para que tudo não fique tão agrupado Vamos clicar com o botão direito do mouse no contêiner de margem e agora adicionar um contêiner VBox Assim, podemos organizar todo o resto verticalmente. Você já pode ver o contêiner de margem, meio que espalhando as bordas um pouco para os lados. Queremos adicionar a isso, provavelmente, nosso texto do título. Portanto, podemos adicionar isso como um rótulo de rich text. Tudo bem, clique em Adicionar uma etiqueta secundária em Rich Text. O motivo para torná-lo rico em texto em vez de um rótulo normal é que, em textos ricos, você pode fazer coisas como código BB, que é bom se você quiser aplicar um efeito de arco-íris ou balançar o texto para cima e Portanto, é apenas mais poderoso do que um rótulo de texto normal. Tenho certeza de que tecnicamente tem um custo de recursos associado a ele, mas alguns textos animados na tela não vão atrasar você Então, vamos colocá-lo aqui, subindo o nível do texto. Podemos ver que não está realmente surgindo aqui. Portanto, precisamos revisar o conteúdo adequado e verificar se ele é verdadeiro. Agora nosso texto vai aparecer lá no centro. Também queremos centralizar esse texto, então mudaremos o alinhamento horizontal aqui para o centro Ok, agora está centralizado. Vamos colocar um ícone abaixo para que possamos mostrar um gráfico de quatro horas acima Então, vou clicar com o botão direito do mouse no contêiner VBox e adicionar um nó filho Digamos que um rack de textura. Adicione isso e podemos selecionar uma textura. Portanto, qualquer gráfico que quisermos usar em nosso projeto funcionará. Vamos ver se podemos carregar algo rapidamente. Então, se eu pesquisar, digamos 64 por 64 para obter a textura de maior resolução, vamos pegar um desses ícones, um que queremos usar e depois aumentá-lo ainda mais. Então, eu realmente queria usar isso como parte de uma textura de atlas Então, se você o selecionou, clique com o botão direito do mouse e vá para Copiar. E no menu suspenso aqui, faça a textura do atlas. Clique na textura do atlas e, em seguida, clique com o botão direito do mouse em colar o final do atlas Agora podemos selecionar qual ícone queremos usar a partir disso. Então, qualquer coisa que você ache que parece boa, há muitas opções. E esta é a folha de sprite de textura de 64 por 64 do pacote de ícones Isso era óbvio, então um dos três ativos artísticos que temos para o projeto. Então, algo como essas espadas gêmeas ou a espada brilhante poderia funcionar muito bem Qualquer coisa que fosse como uma figura humana brilhante, meio que implicando : Oh, eu subo de nível Eu fiquei super forte, como, por exemplo, especificamente assim, ou no projeto base, usei esse, que é mais um raio, mas também poderia funcionar Ok, então desta vez, vou escolher aquele em que parece um feixe de luz gigante em vez de um raio E vou bater de perto. Portanto, temos nosso ícone exibido na textura reta. O alongamento não é realmente como queremos, então queremos mudar o modo de alongamento para manter o aspecto centrado, acredito que seja a melhor opção aqui E isso funcionará muito bem, acho que, seguindo nosso ícone de subida de nível, vamos adicionar um bloco de texto, que diremos ao jogador : queremos fazer uma das poucas seleções Então, vamos clicar com o botão direito do mouse no contêiner do VBux, adicionar outro rótulo de rich text e, em seguida, faremos algo semelhante Verifique a adequação ao conteúdo. E então, para o texto, diremos, escolha uma das opções de subida de nível abaixo. Como pretendemos que a fonte Pixar apareça aqui em nossa tela real vez de ir ao mundo toda vez, para verificar como ela ficará com o tema real do jogo, vamos até a seleção básica de aumento de nível do nó da interface e atribuir o tema aqui também Então, no inspetor, carregue rapidamente o tema e, em seguida, isso atualizará nosso texto Agora você pode ver que, com essa fonte diferente, o texto realmente cabe em uma linha. Essa é uma grande diferença. Vamos clicar no rótulo Rich text dois e centralizá-lo. Ok, a seguir, vamos pegar esse título e torná-lo um pouco mais interessante adicionando um arco-íris e um efeito de onda com o código BB Então, verifique o código BB ativado aqui e vá para o início do texto no canto superior esquerdo. Vamos colocar colchetes para código BB, arco-íris e, em seguida, espaço FREQ para frequência igual a 0,5 espaço SAT é igual Essa é a saturação. O valor do espaço é igual a um e, em seguida, finalize os colchetes e você terá um efeito arco-íris aqui Agora, para garantir que isso termine, você vai até o final do texto e, em seguida, coloca colchetes Rainbow E aí temos nosso efeito arco-íris animado na janela de exibição E também podemos alterar as configurações aqui. Então, se você quiser que seja menos vibrante, tente levar a saturação para 0,5, e agora você terá um arco-íris mais manso aparecendo lá Eu meio que gosto disso, então vou ficar com ele. Agora, vamos também adicionar o efeito de onda. Então, volte para casa novamente para ir para o início da nossa caixa de texto, ou você pode simplesmente clicar lá no canto superior esquerdo Em seguida, faça outros colchetes e digitaremos WA VE para o espaço de onda AMP para a amplitude igual a 50 Essa é a altura que ela vai entre as ondas. E então a frequência espacial ou FREQ é igual a dois. Essa é a frequência com que ele faz uma onda e depois termina com o colchete direito Ok, e então você quer ir até o fim depois do arco-íris aqui em cima e fazer os colchetes Isso significa que, se você adicionar texto extra depois disso, ele não terá o efeito de onda porque encerramos o efeito em nosso bloco de texto. Então, Controle Z, podemos ver nosso texto sendo animado lá. Isso é muito legal. Talvez queiramos que a amplitude diminua um pouco, então vou reduzi-la para 30 Então, se assistirmos à nossa animação, podemos ver que o texto é animado praticamente na parte inferior ou superior da área da etiqueta Acho que se tivermos uma amplitude de 50, como tínhamos antes mesmo de ser cortada. Então isso não é o ideal. Se estiver muito subindo ou descendo, podemos adicionar um pouco de preenchimento a esse rótulo específico acessando substituições de tema E então queremos ir para estilos normais e deixar uma nova caixa de estilo vazia porque não há plano de fundo. Expanda isso, vá para as margens do conteúdo e, em seguida, podemos fazer a parte superior e inferior, alguns pixels de deslocamento Então, vou tentar fazer com que a parte superior seja menos três e a parte inferior menos três. E então o que podemos fazer é adicionar uma margem de conteúdo aqui na parte superior e inferior. Então, vou fazer com que seja como dois pixels na parte superior e dois na parte inferior. Ok, e isso basicamente fará com que nossa caixa fique um pouco maior do que seria por padrão. Então, essa é outra solução se você não quiser simplesmente adicionar um monte de novas linhas na caixa de texto. Acho que essa também seria outra opção mais rápida. Mas também um pouco menos preciso. Então, finalmente, para isso, se quisermos que o texto seja maior, podemos acessar as substituições de temas e personalizar os tamanhos das fontes Então, acho que queremos um tamanho de fonte normal, e vamos aumentá-lo para 24. Ok, esse realmente parece um pouco embaçado. Vamos tentar 32, certo? Ok, então eu acho que para essa fonte específica porque é a Pixar, existem números de escala muito específicos os quais você precisa definir o tamanho do pixel Então, se eu dissesse que é algo como 22, acho que não é um múltiplo de oito ou 16, então não vai funcionar. Então, vamos fazer 32 em vez de tê-lo lá para que seja renderizado corretamente. A propósito, essas substituições, se você quiser, você também pode dedicar algum tempo personalizando-as e os temas especificamente Mas se for algo único como esse, talvez seja mais rápido atribuir seus valores personalizados especificamente a esse cabeçalho Somente se você tiver muita interface de usuário em todo o jogo e quiser personalizá-la em um local centralizado , fazer muitos temas faz sentido Em vez de usá-lo apenas para fontes, você também pode personalizar os tamanhos das fontes ou adicionar cabeçalhos personalizados 44. Ladrilho 43 Projetando a UI de seleção de recompensa e ajustes finais: Tudo bem, agora precisamos criar nossas caixas de seleção verticais Então, isso vai ser uma subinterface de usuário. Vou criar um novo nó aqui em cima. Digamos que seja uma interface de usuário, mas vou clicar com o botão direito do mouse aqui e mudar seu tipo para um contêiner de painel. Vamos apenas transformar a raiz aqui em um contêiner de painel. E isso será em tamanho real por padrão, expandindo-se em todos os lugares. Vamos renomeá-la para Seleção de recompensas. E vou salvá-lo na pasta UI. Ok, agora vamos para a seleção de Lavop, e vou colocar três delas na hierarquia Então, procure uma recompensa no projeto e coloque uma delas no VBox Vou duplicá-lo mais algumas vezes. E você verá que o problema imediato é que existem três, mas são todas verticais. Portanto, precisamos de outro contêiner HBox para torná-los horizontais Então, clique com o botão direito do mouse no contêiner VBox e adicione um contêiner HBox do nó filho e coloque as três seleções de recompensa sob o Agora você deve ver se você clicar no contêiner HBox se cada um deles tem uma posição de deslocamento um do outro Mas, no momento, eles não se estendem pela tela. Então, precisamos ir para a seleção de recompensas, que será o layout, o tamanho do contêiner Queremos expandir na horizontal. E já que estamos nisso, vamos expandir verticalmente também. Controle para salvar, volte para a seleção de subida de nível. E agora podemos ver que eles estão meio que no sentido de uma coluna. Cada um deles ocupa um espaçamento uniforme do espaço da esquerda para a direita e se encaixa no contêiner do painel principal Então, isso é mais parecido com o que estamos procurando. Na seleção de recompensas, vamos clicar com o botão direito do mouse na parte superior e adicionar um nó. Então, isso vai ser um rótulo Rich Text no rótulo Rch text, vamos colocar o texto Diremos o nome do colchete e eu verificarei o conteúdo do Fit Podemos ampliar aqui para ver. Então, para a seleção da recompensa, vou clicar em Seleção de recompensa, e vamos pegar a predefinição da âncora e vamos pegar a predefinição da âncora e virar no canto superior esquerdo, ok E aqui embaixo, precisamos de um contêiner de margem. OK. Então, se olharmos aqui, se olharmos aqui, não há espaçamento entre nossos rótulos e a borda desse painel Então, vamos adicionar um contêiner de margem abaixo da seleção de recompensa. Clique com o botão direito do mouse em Adicionar contêiner de margem secundária e, em seguida, torne o rótulo Rich text filho dele. O contêiner de margem substituirá constantes de tema e, digamos, talvez três pixels para as margens esquerda, superior, direita e inferior aqui Agora vamos pegar a seleção de recompensa raiz e vou mudar sua predefinição de âncora para, digamos, canto superior esquerdo Mas também vamos analisar a seleção de recompensas e ampliá-la um pouco para que possamos pelo menos ver com o que estamos trabalhando aqui. Não precisamos esticar a tela inteira porque isso é enganoso, mas queremos poder ver nosso conteúdo vertical E podemos ir para a seleção de aumento de nível para ver como isso vai ficar em qualquer momento após o redimensionamento e esse contêiner de interface Até agora, parece bom. No entanto, queremos centralizar esse título. Então, vou clicar no rótulo Rich text e vamos fazer o centro de alinhamento horizontal Além disso, para o dimensionamento vertical do contêiner aqui e o controle, quero começar com o Shrink Então, isso garantirá que ele não se expanda mais do que o necessário. Se formos para aumentar o nível de seleção, veremos nossos rótulos centralizados aqui Ok, agora precisamos do nosso espaço reservado para ícones. Então, clique com o botão direito do mouse em Margin Container, adicione uma textura reta e, em seguida, podemos selecionar um ícone do nosso projeto Então, vamos fazer uma nova textura do Atlas. E aqui, vou carregar rapidamente um ícone de atlas do pacote de 16 por 16 Vamos fazer essa região e selecionar um espaço reservado. Então, algo para subir de nível, algo assim parece muito bom. E vou bater de perto. Agora, precisamos ter certeza de que isso está realmente organizado corretamente, então precisaremos de um contêiner VBox sob o contêiner de margem Então, clique com o botão direito do mouse no contêiner de margem, adicione um contêiner VBox pregado como filho e transforme o título e a textura em filhos dele Ok, agora vai se organizar adequadamente. precisamos garantir que isso mantenha sua proporção, No entanto, precisamos garantir que isso mantenha sua proporção, para que não pareça estranho Portanto, no inspetor de texto, altere o modo de alongamento para manter o aspecto altere o modo de alongamento para manter o Também deve manter o aspecto centrado. OK. Lá. Isso parece mais apropriado. Talvez também queiramos acessar o layout e definir um tamanho mínimo de ícone. Então, aqui, vou pegar o tamanho mínimo personalizado e dizer algo como 48 por 48. Ok, isso meio que expandirá isso. 32 por 32 é bom. Então, isso significa que se seu ícone for menor que 32 por 32, ele será automaticamente escalado para esse tamanho. Ok, vamos adicionar um texto descritivo, para que eu possa controlar C o rótulo de rich text e, em seguida, clicar no contêiner VBox, controlar V e colá-lo E colocaremos a descrição entre colchetes aqui. Obviamente, podemos ver que isso é muito grande para essa área, então talvez precisemos trabalhar em nossos tamanhos de fonte posteriormente. E então, por fim, queremos um botão para selecionar a opção. Então, vou clicar no contêiner vBox e adicionar um botão. Então, aqui provavelmente vamos querer apenas um botão normal. O que permite que você tenha um ícone, para que possamos carregar rapidamente um ícone de teste, mesma forma que fizemos antes, com menos textura, expandi-lo. Carga rápida da folha de sprites de 16 por 16. Faça Editar região e escolha um ícone. Então, talvez algo como a espada com um símbolo de subida de nível faça sentido. OK. Agora podemos ver nosso botão como um ícone. E então, na caixa de texto, poderíamos dizer escolha indicando o que estamos fazendo aqui Agora, se formos até nossa janela de seleção de subida de nível, podemos ver nossas três partes da interface aparecerem aqui embaixo, temos três botões que conectaremos para escolher mais tarde. Temos nosso título animado. E é mais ou menos assim que nosso modelo vai ficar. É só uma questão de fornecer as opções de seleção, conectá-las ao nosso jogador e, em seguida, atualizar nosso jogador assim que ele fizer uma Será apenas uma questão de preencher a lista com as opções disponíveis e aplicá-las ao jogador assim que ele fizer sua seleção Ok, então você pode notar que há um pequeno problema em que às vezes a borda de nossos ícones meio se sobrepõe aos ícones vizinhos Então, para corrigir isso, podemos acessar a seleção de recompensas e verificar o clipe do filtro. Para o botão. Então, quando você fizer isso, se você for até aqui e aumentar e diminuir o zoom, isso deve resolver o problema ali mesmo, para que você não veja mais pixels sobrepostos Além disso, para o nível de seleção no mundo, ele pode estar tecnicamente centrado aqui Mas você pode ver que está indo para baixo e para a direita a partir desse ponto central. Então, na verdade, não vai aparecer centralizado na tela. Para editar isso, acho que seria uma boa ideia pegar nossa camada Canvas e clicar com o botão direito do mouse em salvá-la como uma nova cena em nosso projeto de interface do usuário. Então, vou dizer gameplay UI Canvas como nome, e então vamos abri-lo. Ok, agora, se olharmos para Hue, podemos ver com muito mais clareza onde nossos objetos estão posicionados na tela e seu tamanho em relação ao ponto de vista, vez de ter uma visão de mundo desordenada Então, podemos ver, é claro, que nossa seleção de jogadores, UI, precisamos clicar nela e provavelmente dobrar o tamanho. Então, em escala, vou pegar a escala e fazer dela dois. Isso pode até precisar subir para três. Sim, vamos escolher três por padrão. Ok, então, para lidar com esse problema nosso contêiner de painel basicamente vai para a direita e para baixo, em vez de ficar centralizado aqui Queremos entrar na cena de seleção de Love Up e depois ir para o painel de contêiner, eu acho. E à direita, precisamos levar o modo de layout para âncoras e depois centralizá-lo aqui Sim. Ok, aí. Agora temos o que estamos procurando. Então, isso basicamente faz com que tudo o que é um subobjeto seja centralizado nesse ponto de ancoragem, onde, se formos para a interface do usuário do Canvas agora, ela será centralizada corretamente Ok, muito rápido, vamos entrar no roteiro da seleção de Llevo E quando estiver pronto, queremos ocultar nossa seleção de subida de nível. Então, vou digitar e me esconder aqui. E isso garantirá que, quando iniciarmos o jogo, ele se esconda por padrão. Vamos clicar em play. Vamos para o LeveOp obtendo EXP. E aí temos nosso seletor LevelUp pop-up. Temos três botões para escolher . Eles ainda não fazem nada. Podemos decidir mais tarde que não queremos pausar a música, como o que acabou de acontecer, mas, além disso , tudo está funcionando O jogo está completamente pausado e nossa interface está aparecendo. 45. P44 Criando um sistema de classificação de armas para atualizações de jogos: Para que nosso sistema de subida de nível funcione, na verdade, precisamos de algumas atualizações para preencher a lista aqui do nosso menu de subida de nível Então, geralmente, serão atualizações de armas. Portanto, também precisamos configurar um sistema de nivelamento para nossas armas Então, se olharmos para a cena do jogador, temos a arma de lança padrão, que tem uma definição de arma Portanto, a definição de arma é muito simples aqui por enquanto, mas precisaremos adicionar uma atualização de arma. Mas adicionaremos aqui uma série ou dicionário de atualizações de armas para que possamos avançar para o próximo nível e realmente obter quanto dano essa arma deve causar em qualquer nível, para que , quando lançarmos nossa arma, ela use as configurações apropriadas E isso também pode incluir coisas como o tempo de resfriamento ou quantos alvos uma arma pode atingir. Há muitas propriedades diferentes que você pode configurar para seu sistema de armas. Então, se entrarmos no script de armas de lança, podemos avançar na definição da arma Você pode ver aqui que eu já criei um método de resfriamento, que retornará com base no nível no resfriamento da arma Então, aqui, se definirmos nossa matriz e passarmos o nível real da arma, poderemos recuperar o conjunto correto de estatísticas de nossa arma no nível atual E então também precisaremos gerar um método get seen. Então, atualmente, isso é apenas carregar a cena da lança diretamente Mas quando estamos aprimorando nossa arma, podemos adicionar a opção cenas de projéteis completamente diferentes gerar cenas de projéteis completamente diferentes, mas não queremos necessariamente fazer isso em todos os níveis, então poderemos fazer com que ela volte ao projétil da arma original e simplesmente atualizar Então, vamos fazer isso criando algo como um nível de arma ou uma definição de nível de arma. Então, vou para o sistema de arquivos e vamos para as armas. Vamos clicar com o botão direito do mouse e criar um novo script aqui. E então vou chamá-lo de algo como nível de arma, que por si só será um recurso. Então, vamos criar isso. Abra o script do nível da arma. Vamos até o topo e criaremos o nível de arma com o nome da classe. Então, isso define as estatísticas da arma nesse nível específico. Portanto, uma arma pode ter quantos níveis você quiser e progredirá em potência à medida que for atualizada. Assim, podemos colocar aqui algumas estatísticas que gostaríamos de poder acessar para um nível diferente da arma. Então, um óbvio seria o resfriamento. Então, podemos dizer que em export var, esfrie, e isso será um float, e podemos usar como padrão 1.0 Ok, então vamos salvar isso bem rápido. Vou fechar todos os meus outros scripts aqui, então clique com o botão direito do mouse e feche tudo para que possamos ver o que estamos fazendo. Ok, e então abra o nível da arma e a definição da arma aqui. Ok, então esses seriam os únicos dois com os quais estamos trabalhando aqui. Então, nós queremos, eu diria, um dicionário, se quisermos ser consistentes com nossos níveis de jogadores. E no Export VR, níveis, que serão um dicionário de números inteiros e o nível da arma Então, para o tempo de recarga do Git, queremos obter o nível e, em seguida, retornaremos o tempo de recarga das estatísticas do Então, o nível de VR será igual aos níveis dot Git e obteremos o nível P. E retorne null por padrão. Então, agora queremos remover o sublinhado do nível P porque finalmente estamos usando essa variável Agora, ele não pode inferir o tipo aqui, então temos que dar a ela o tipo de nível concreto da arma e, em seguida, retornaremos o tempo de recarga de pontos de nível Ok, então clique com o botão direito no nível da arma e faça o símbolo Loup. Ok, certifique-se de que está realmente lá. Então, em get cooldown, ele encontrará o nível da arma Se não conseguir encontrar o nível da arma, na verdade haverá um erro aqui. Eu pude ver que estamos usando muito essa linha. Então, na verdade, eu também vou colocar aqui uma função de nível de arma Git O que exigirá um número inteiro de nível P, e isso retornará um nível de arma Então, podemos simplesmente devolver isso. E então, em vez disso, o que podemos fazer aqui é , digamos, obter o nível da arma. Passe um ponto de nível p igual para baixo. Agora, uma boa razão pela qual faríamos isso é que se quisermos adicionar algum código posteriormente, digamos que não haja um nível de arma e queiramos usar o nível anterior como padrão, ou queremos dividir o erro. Podemos fazer tudo isso dentro dessa função G (função de nível de arma). E então, em todos os outros lugares que chamamos de Obter nível de arma, todo esse código extra será pré-manipulado Então, isso meio que configura se precisarmos fazer com que a função seja danificada, função g max atinja, etc Isso reduzirá nosso código posteriormente e o centralizará nessa Mas, por enquanto, especialmente quando estamos fazendo protótipos, acho que definitivamente quero saber imediatamente se esqueci de configurar um nível de arma em que esperaríamos que houvesse um nível de arma definido na definição da arma Então, na verdade, estou totalmente acordo com o fato de que isso gera um erro assim que tentamos reduzir o ponto quo em um nível de arma nulo É por isso que vou deixar as coisas assim por enquanto. Ok, agora vamos entrar no nível da arma e configurar algumas outras propriedades que queremos modificar por nível. Outra óbvia seria o dano que uma arma pode causar. Então, em export var damage, podemos realmente causar danos aos homens ao MAX, se quisermos que seja um pouco mais interessante. Então, se dissermos em export var men damage, e digamos que seja um float, podemos padronizá-lo para 10.0, e então temos em export var Max damage, que será um float que será um E vamos definir isso como 20 por padrão, quaisquer números que você considere um bom ponto de partida, você vai ajustar. Quase sempre para cada recurso de nível de arma. Como mencionei, provavelmente também queremos o máximo de acertos Então, no Export V, o máximo de acertos será um número inteiro Vou defini-lo igual a 1,0. Ah, além disso, o dano masculino e o dano MÁXIMO, esqueci que estamos lidando com números inteiros no jogo, então vou mudar isso para Então, vou mudar isso para inteiro em ambos os casos para ser consistente Obviamente, você pode usar flutuadores em combinação com números inteiros Mas acho que, nesse caso, quando sempre queremos que o dano não seja decimal, é melhor ser consistente em todos os nossos scripts OK. E então, da mesma forma, o acerto máximo diz que o número inteiro não deve ter um ponto decimal Provavelmente também vamos querer uma variável de velocidade aqui em algum lugar. Então, exporte a velocidade da variável, e isso será uma flutuação Vou configurá-lo para 100,0, aproximadamente pixels por segundo. Depois, um rápido comentário lá também. Então, agora temos um monte de propriedades. Queremos configurar o recurso em nossa definição de arma de lança Ok, então vamos diminuir o zoom e clicar na arma de lança. Aqui à direita, temos nossos níveis de armas, então os configuramos. Portanto, o nível corresponde não à posição da matriz, mas ao nível real da arma. Então, queremos começar com um aqui. E então queremos criar um novo nível de arma. Ok, então em nosso nível de arma, esses podem ser nossos conjuntos básicos. Por que não adicionamos o par de valores-chave, e esse será o padrão para nossa lança de nível um Vamos adicionar dois e depois um novo nível de arma. E queremos aumentar os danos aqui. Então, eu vou dizer 15 a 25, e talvez a velocidade seja um pouco mais rápida, então 110 para a velocidade. Com o resfriamento, podemos lançar um pouco mais rápido, então vou dizer 0,9, e o máximo de acertos será definido para um ainda porque adicionar um golpe máximo extra é muito importante. Isso pode ser como dobrar seu dano de forma eficaz. Então, vamos adicionar isso. E então vamos fazer o nível três, novo nível de arma. Vamos dizer 20 a 25 de dano, a velocidade, talvez 115, e depois o resfriamento é 0,9, mas aumentamos o máximo de acertos para dois Então você pode meio que ter a ideia aqui. Quase sempre queremos que alguns números subam. Eu acho que cada nível é um upgrade em relação ao anterior. Não precisamos necessariamente alterar as atualizações em um fator linear Então, por exemplo, um nível pode ser um grande aumento de dano, mas a velocidade do projétil permanece a mesma De qualquer forma, adicione isso e continuaremos em quantos níveis você quiser. Ok, então, para continuar, vamos fazer quatro. Vamos colocar um novo nível de arma aqui, e isso pode ajudar a expandir o nível de arma anterior para que você saiba o que precisa melhorar. Então, começamos com 20 homens danificados. Vamos fazer 25 de vez em quando e depois 30 para o dano do MX e a velocidade, 120, o resfriamento de 0,8 O máximo atinge dois. Adicione um par de valores-chave. Apenas continue. Ok, e acabei de adicionar um quinto para me divertir. Então, nesse caso, você pode ver as estatísticas ali mesmo se quiser copiar. Uma estatística importante que eu realmente esqueci seria o número de projéteis gerados Então, vamos exportar projéteis var, e isso será um número inteiro igual a Portanto, o número de projéteis por instância por lançamento é uma propriedade muito forte Então, se quiséssemos que um nível fosse extremamente forte , poderíamos dizer, talvez o nível cinco. Temos dois projéteis por lançamento, e isso fará com que a arma cause muito mais dano Agora, não queremos que os projéteis apareçam exatamente ao mesmo tempo na maioria dos casos Uma forma seria compensá-los para que você possa ver onde eles vão aparecer Outra opção que você pode adicionar seria atrasar após a ocorrência de um lançamento, quanto tempo antes de cada projétil se estender. Então, você poderia dizer, vamos realmente adicionar os dois como uma opção. Então, poderíamos dizer em Export var offset ou span offset. Vai ser um carro alegórico. ser igual a zero, zero. E então, na exportação de VR, atraso na geração é uma flutuação, e diremos 0,05 segundos Então, isso vai ficar mais ou menos assim. desova é o deslocamento máximo para a posição de amplitude instantânea do projétil Então, a que distância do ponto central ele pode estar quando aparece E então, o atraso de alcance será o tempo e segundos de espera entre os vãos adicionais do projétil, e devo dizer que, após o primeiro, esse é o valor chave Ok, então, no próximo vídeo, trabalharemos para pegar esses níveis de armas e fazer com que possamos realmente selecionar como aumentá-los dentro de nossa interface de usuário. 46. Itens de armas P45 para aumentar o poder da sua arma: Ok, então, para a próxima parte, precisamos introduzir a habilidade de nossa interface de seleção de subir de nível para obter o item para a atualização da arma, para que possamos aumentar o nível da arma que está realmente ativa no jogo. Então, a primeira etapa será criar uma lista de opções ou recurso dentro de nossa seleção de subida de nível, que usaremos para preencher as opções aqui embaixo com base em uma seleção aleatória das viáveis disponíveis Vejo aqui no canto inferior esquerdo que os projéteis estão na pasta de níveis Na verdade, vou transferir isso para armas que façam mais sentido. Então, como não há nada na pasta Levels, vou renomeá-la para configurações porque o que realmente estamos fazendo é configurar uma lista de atualizações de armas ou outras atualizações que podemos escolher em nosso nível de E, na verdade, podemos diferir isso, dependendo do personagem, ou podemos diferir dependendo do nível que estamos carregando em nosso jogo, mas queremos ter a opção personalizá-lo de qualquer maneira. Então, vamos criar um novo script, e vou chamar essas opções de nivelamento de ponto gD Este será um recurso, para que possamos editá-lo no GIDOEditor E então eu vou entrar aqui. E digamos que opções de nivelamento de nomes de classes. No início do curso, apresentamos os captadores. Agora, esses captadores só existem atualmente como uma cena no mundo do jogo, coletados e imediatamente a EXP é adicionada aos Então, não precisamos de um item especificamente porque essa EXP só modifica uma estatística. Mas se quisermos algo mais complexo, como um aumento de saúde ou a habilidade de aumentar o nível de uma arma , precisamos de uma classe de item mais concreta dentro do nosso jogo, e praticamente todos os jogos do tipo RPG terão isso em algum momento Então, queremos exportar uma lista de itens que podemos usar imediatamente com nosso player. Então, vou exportar itens, e essa será uma matriz de, digamos, itens por enquanto. Agora, não criamos uma classe de item. Então, vamos criar uma pasta no canto inferior esquerdo para itens. Vou clicar com o botão direito do mouse e criar uma nova pasta. Vou chamar esses itens. E aí dentro, vou clicar com o botão direito do mouse e criar um novo script. E este será o item dot gD que se estende de Resource. Ok, então dentro daqui, faremos o item do nome da classe. Especificamente para um jogo semelhante a um sobrevivente, talvez não tenhamos necessariamente itens que existam em um inventário Portanto, eles ainda precisam se inscrever imediatamente. Mas a forma como eles se aplicam é mais complexa do que apenas o ExbPickup ser uma atribuição imediata Então, para que possamos aplicar nossos itens a um jogador ou alvo, pelo menos, vou criar uma função. Digamos que a função try apply, que pegará um alvo P, não dois D, e retornará um booleano Portanto, tente aplicar porque pode haver circunstâncias em que ele falhe, e pode ser útil em algum lugar do nosso código ter esse feedback sobre se foi bem-sucedido ou também podemos querer uma função can apply para que possamos verificar com antecedência se ela é realmente viável ou Então, direi que a função pode ser aplicada, e isso passará pelo alvo, sem dois D e retornará de booleanos Então, por padrão, direi return false aqui porque esse é um item básico. Não podemos aplicá-lo, e vou apenas dizer return false aqui também. Então, vou colocar isso em um aviso de que não podemos aplicar o item básico a um alvo e, em seguida, vamos criar nosso item de arma porque é com isso que estamos mais preocupados primeiro. Então, vou clicar com o botão direito nos itens, criar um novo script, e esse será o item de sublinhado da arma, que será herdado do item como classe base, então criaremos Então, item de arma aqui, vamos até o topo e criaremos item de arma com o nome da classe que é um nó dois D. Isso retornará Boolean Portanto, precisamos de uma forma de acessar o carregamento de armas do personagem, se ele tiver um Então, uma forma simples de dizer isso seria: far loadout é igual a p target dot find child, e vamos procurar o carregamento de armas Está bem? E isso deve retornar um tipo de carregamento de armas Então, vamos realmente mover isso para sua própria função. Então, a função get loadout retornará a carga de armas E então vamos devolver isso em vez disso, devolver o carregamento de armas ptarget dot Fine Child Então, precisamos passar o Ptarget aqui. E então podemos inferir o tipo. Então, vou fazer dois pontos iguais, obter carregamento no pTarget e depois retornaremos se isso E então queremos verificar se o carregamento tem a definição de armas que estamos tentando aplicar no momento Então, poderíamos exportar a definição de VR. E essa é uma definição de armas , melhor dizendo. Ok, depois de obter o carregamento, queremos verificar se a arma existe ao lado do Se isso acontecer, veremos se há espaço para subir de nível ou se já atingimos o limite de nível. Então, dentro do carregamento, precisamos saber quais armas estão realmente embaixo dele dentro desse sistema Então, quando estiver pronto, podemos obter todos os carregamentos preexistentes e, em seguida, adicionaremos um método para que possamos adicionar um novo que o anexará à matriz, mantendo referência a todas as Então, digamos que as armas var aqui uma matriz de armas dois D e, na função sublinhado pronto, que retorna vazio, queremos pegar todas as crianças do tipo arma Portanto, para arma, encontre crianças, as aspas vazias da sequência padrão não correspondiam ao nome Mas para o tipo, vamos usar a arma dois D, e o revestimento é importante aqui porque esse é o tipo de nome da classe Então, isso só devolverá crianças por meio da arma tipo dois D. E então podemos dizer que armas pontuam a arma Penn. E agora, quando o script começa, temos todas as armas pré-existentes. Poderíamos dizer que temos uma função de adicionar arma, que usará uma arma P, que é um tipo de arma, dois D, em vez de Vitun vazia e diremos armas, arma Penn E queremos ter certeza de que é filho dessa arma. Então, fazemos isso em uma função. Diremos Adicionar filho da arma P. Isso vai ser bom por enquanto. Então, vamos entrar no item de armas. Temos o carregamento para que possamos verificar se ele já o tem. Então, depois de obter o carregamento, queremos obter a arma associada a essa definição de arma Então, digamos que nossa arma será igual à arma LoadOug, com base em uma com base em Então, vamos dizer a definição aqui. Agora, vamos entrar no carregamento de armas e fazer a função arma G, com base na definição Então, definição P. É uma definição de arma. Vamos devolver uma arma para D. E digamos que para arma em armas, se a definição da arma for igual à definição P, vamos devolver essa arma. Caso contrário, retornaremos null. Como só precisamos vasculhar algumas armas, ter um pequeno loop como esse será perfeitamente normal, não é realmente um problema. Além disso, se você quiser limitar a quantidade de armas que um jogador pode ter , você pode dizer algo mais como, na exportação, as armas do VR Max são um número inteiro de seis na parte superior E então poderemos verificar se também há espaço. Então, podemos dizer que a função tem espaço, e esse será um tipo de retorno booleano, e diremos apenas que devolver armas dot si é menor que o máximo de armas Ok, então isso é apenas uma pequena força de função auxiliar Agora, de volta ao item de arma, se eles têm a arma, queremos ver se podemos subir de nível. Pode até fazer sentido declarar a arma do tipo dois D aqui, embora isso já tenha sido inferido da chamada de função da arma Ok, então primeiro, se não houver arma, então se a arma for igual a nula, retornaremos que a carga tem espaço para determinar se podemos aplicar Porque se a arma não existir no sistema de armas, só precisamos ver se há espaço para adicionar uma nova. Caso contrário, se houver uma arma, queremos ver se podemos subir de nível. Então, diremos que devolva a arma. Pode ser algo como subir o nível C ou ter o próximo nível. Acho que Has Next Level soa como um bom nome para. Então, agora precisamos dessa função dentro de nossas armas para o script D. Então, em armas para D, queremos usar o nível em relação à definição e apenas verificar se há um próximo nível. Então, na parte inferior, vamos criar nossa função. Portanto, a função tem o próximo nível. Isso retornará Boolean. Então, digamos que a função funcione no próximo nível, que será um nível de arma igual à definição Obtenha o nível de arma do nosso nível atual mais um, que pode retornar nulo Então, retornaremos que o próximo nível não é igual a nulo. Porque se houver um próximo nível , podemos atingir o próximo nível. Podemos subir de nível. Se não houver, então atingimos o limite de nível ou esquecemos de definir um nível Então, podemos ter definido o nível sete, mas definimos o nível seis quando estamos no nível cinco? Porque cinco pode ir para seis, mas não podemos simplesmente pular para sete, pelo menos normalmente. Então, isso deve atender às nossas necessidades para verificar se podemos nos inscrever. E então, se vamos aplicar, diremos função, aplicar. E deixe-me verificar a classe base aqui só para ter certeza de que tentaremos aplicar. Na verdade, pode fazer sentido copiar isso. OK. E então vamos substituir isso aqui embaixo apenas declarando novamente a mesma função Então, primeiro, precisamos pegar a arma se quisermos nos inscrever. Então, a arma Var é uma arma dois D, e isso vai ser igual à arma LoadOug de Então, se a arma não estiver lá, então já falhamos. Então, se a arma for igual a nula, retornamos as quedas. Mas também precisamos obter o carregamento novamente. Portanto, os carregamentos de Var serão do tipo inferido do alvo G loadout Então, estamos obtendo a carga no alvo ao qual estamos tentando nos candidatar Então, uma vez que temos a arma, queremos usá-la. Então, vamos dizer que a arma dot-tri sobe de nível, e isso retornará, independentemente de termos sucesso ou não Então, retornaremos esse valor. Agora precisamos definir a arma dot tri level up e arma two D. Então, vamos descer aqui e ver a função, função tri level up, e vamos retornar um Ok, então vamos dar uma olhada no topo do nosso script em D de arma 2. Podemos ver que temos o nível e o nível da arma existe na definição da arma para ser um pouco mais eficiente e poder acessar nossas informações atuais. Depois de já termos subido de nível, também poderíamos ter uma variável local Poderíamos dizer que nosso nível de arma é um nível de arma. Então, na leitura, digamos que o nível da arma seja igual ao nível de definição da arma Dot Git em nosso nível atual E então, sempre que subirmos de nível, também vamos definir isso. Dessa forma, se precisarmos ver as estatísticas do nosso nível atual de arma, basta acessar esse valor aqui. Então, basicamente encontramos o valor em nossa definição uma vez e, até subirmos de nível novamente, temos acesso às informações nesse nível de arma. Ok, agora com o Trevelu, queremos chegar ao próximo Portanto, nossas estatísticas de próximo nível serão iguais à definição de obter o nível da arma em nosso nível mais um. Portanto, se as estatísticas do próximo nível forem iguais a nulas, retornaremos false Caso contrário, diremos que o nível da arma é igual às estatísticas do próximo nível e dizemos que o nível mais um. Nível mais é igual a um, e retornamos verdadeiro Ok, então aqui está nossa função de subir de nível. Ok, a última coisa que vamos fazer neste vídeo para o item de armas é realmente criá-lo. Então, nos itens, clique com o botão direito crie um novo recurso, pesquise o item de armas, pressione Enter, vamos colocar isso nos itens. Então, vamos dizer item de lança. E se você clicar duas vezes no item da lança, você pode ver que temos um lugar aqui para a definição Queremos que a definição seja exatamente a mesma definição de nossas armas de lança Então, se você clicar em arma de lança, você pode ver que ela tem a definição de arma Vamos clicar com o botão direito aqui e salvar isso dentro das armas. Então, na raiz, vamos às armas, e temos a definição de lança lá Queremos clicar duas vezes e substituir isso. Está bem? Então, aqui está nossa definição real de arma de lança, e agora esse é um recurso compartilhado Assim, podemos clicar no item Lança e queremos carregar rapidamente a mesma definição de lança Então, agora o item de lança será vinculado dessa forma à arma de lança Para que possamos reutilizar a arma de lança 2 D. Vamos salvar esse galho como uma cena Clique com o botão direito em Salvar ramificação como SN. E vamos colocá-la na pasta de armas como arma de lança ponto TCN Ok, agora podemos reutilizar isso em inimigos ou em qualquer outro lugar que precisemos O ponto principal é garantir que eles estejam usando a mesma definição de lança, que é muito importante, caso contrário, o item de lança nunca conseguirá encontrar a arma de lança por meio do Ok, agora fizemos todo o trabalho de base. Então, no próximo vídeo, configuraremos a interface do usuário e faremos que a subida de nível funcione para atualizar nossas armas 47. Ladrilho 46 Crie um sistema de seleção de itens ponderados para recompensas ao nível: Então, neste momento, precisamos adicionar uma lista de itens de armas à nossa seleção de subida de nível, que podemos escolher quando preenchermos a janela Então é aí que entra o script da opção de nivelamento, onde, para um determinado mundo de jogo ou nível do jogo, temos apenas essa variedade de itens que podemos atribuir na seleção de subida de nível Então, no script de seleção de subida de nível, precisamos exportar uma VR para opções, e isso será do tipo opções de nivelamento Ok, então salvamos esse script, e agora, se olharmos para o inspetor e duas visualizações em D, clicamos na seleção Level Up e, à direita, podemos criar nossas novas opções de nivelamento Agora, isso é algo que provavelmente tem um nível muito específico. Portanto, você pode ter um nível um em que tenha muitas opções e, em seguida, o nível dois, talvez seja um pouco mais difícil, então você restringe a lista de itens, ou pode até mesmo ser por classe de personagem, se você decidir seguir o caminho de restringir itens a De qualquer forma, esse será um recurso no qual você deseja clicar com o botão direito do mouse e salvar no projeto. Então, vamos entrar, digamos, na pasta de configurações, já que é por isso que eu coloco o script de opções de nivelamento, e então colocamos as opções de nivelamento de nível um e depois salvamos, então será um ponto E agora podemos atribuir uma matriz de itens. Então, vou aumentar isso para um, e vamos carregar rapidamente o item de arma do item de lança E agora essa é uma das possibilidades que podemos usar dentro do nosso script de seleção de subida de nível. Em nossa hierarquia, queremos que a seleção de subida de nível passe as opções, digamos, para esse contêiner HBox, que poderíamos dizer que é mais parecido com a seleção de recompensas Portanto, em termos de nossa hierarquia, temos a opção definida no nível de seleção de nível superior Quando abrirmos o menu para aumentar o nível de nosso personagem, nossas seleções de recompensas serão preenchidas aqui neste contêiner da caixa H. Então, cada uma das recompensas que pudermos escolher aparecerá como uma opção aqui embaixo. Por padrão, seriam três. Mas, na verdade, isso depende quantos itens temos disponíveis. Assim, poderíamos renomear esse contêiner HBox para algo como um contêiner de caixa de recompensas e, em seguida, clicar com o botão direito do mouse e dar um script Então, vou anexar um script e salvá-lo no UI slash Rewards Box Container O motivo pelo qual estou fazendo isso é porque quanto mais você separa as diferentes funções de sua interface geral em scripts menores separados, mais reutilizável será cada um desses componentes porque você está separando as responsabilidades Portanto, o contêiner da caixa de recompensas será o único responsável por preencher as recompensas que ficarão embaixo dele Então, vamos criar um contêiner de caixa de recompensas com o nome da classe e, em seguida, vamos exportar uma cena cheia para exemplificar cada uma dessas seleções de recompensas Então, eles não vão realmente estar lá. E o BaseUI, eles serão eliminados e somente instanciados quando tivermos uma recompensa para Então, vamos criar uma função populate e isso exigirá uma lista de opções E também queremos saber quantos itens podem ser selecionados ao mesmo tempo. Então, acho que as opções de nivelamento seriam um bom lugar para colocar essa propriedade em vez da própria interface do usuário. Então, vamos clicar com o botão direito em Opções de nivelamento, símbolo de pesquisa E eu vou dizer em export var MAX Underscore Choices, que será um número inteiro, e vou padronizar isso para três E enquanto estamos à frente, quero fazer uma grande mudança nessa variedade de itens. Na verdade, vou transformá-lo em um dicionário de itens para que possamos aplicar um peso a cada um. E isso fará com que, se quisermos priorizar um item como uma opção possível, possamos fazer isso aumentando sua taxa de queda forma eficaz, fornecendo a ele um valor flutuante mais alto ou um valor flutuante menor para itens mais raros Agora, como mudei o tipo dessa variável, significa que preciso redefini-la na seleção de nível. Então, se formos para a seleção de níveis e examinarmos nosso novo dicionário aqui, precisamos fornecer o item. Então, carregue rapidamente esse item de lança e atribua um valor a ele. Poderíamos dizer um, se quisermos. Então, agora esse item de lança tem uma chance de cair de 1,0. E, assim como nos outros casos em que fizemos aleatoriedade com pesos, esse 1,0 é relativo ao peso total de tudo o mais nesta lista Então, agora é 100% porque há apenas um peso a mais de 1,0, então é um em um. Mas se adicionarmos mais quatro itens , teremos 20% de chance. E, claro, como estamos dando três opções, ele vai rolar três vezes. Quando selecionamos um item em nossa lista suspensa, ele também é removido dos pesos gerais Se tivéssemos cinco opções, escolheríamos três delas, três escolhas únicas, devo dizer. Então, vamos até o contêiner da caixa Rewards. Agora temos quantos vamos realmente escolher. Ah, e queremos obter o peso total. Lista de opções, certificando-se de que cada uma esteja disponível para ser usada com o alvo específico. Então, vamos criar outra função para isso. Vou chamar isso de função, gerar escolhas. E assim consideraremos as opções P como opções nivelamento e o alvo P como um nó dois D. Ok, então primeiro, queremos obter as opções restantes da lista de opções Então, se nossas opções restantes forem iguais a, digamos, peso do item Poptionst ou peso dos itens, e vamos duplicar Ok, então a razão pela qual estamos duplicando aqui é porque queremos esse dicionário de itens com seus pesos e vamos duplicar Ok, então a razão pela qual estamos duplicando aqui é porque queremos esse dicionário de itens Para sermos específicos para essa função, não queremos mexer com o dicionário original removendo itens desse dicionário Todas as opções de nivelamento devem permanecer nas opções de nivelamento basicamente pelo resto do jogo, porque essa é uma definição de tempo de edição, e essas são nossas opções restantes de tempo de execução Então, duplicamos a lista e vamos removê-la depois de fazermos cada seleção ou depois de invalidarmos uma Portanto, a duplicata aqui é importante para garantir que não estamos modificando o dicionário original Efetivamente. Agora temos as opções restantes. Queremos filtrar todas as opções que são inválidas. Então, para a opção nas opções restantes, teclas de ponto, por que teclas? Porque as chaves neste dicionário são os itens e os valores são os pesos Portanto, pode ser útil declarar o tipo aqui, embora seja inferido do peso dos itens, é melhor que possamos vê-lo na tela Então eu vou dizer dicionário do item, e então temos o peso. Oh, espere, o peso está flutuando. E aí podemos ver claramente que o item são as chaves. E a flutuação é o valor. Para cada um desses itens, queremos verificar se o alvo pode aplicá-lo? Na verdade, talvez seja melhor chamar esse item aqui. Para o item do tipo item nas teclas de ponto das opções restantes, podemos dizer que, se o ponto do item pode ser aplicado e , como o digitamos aqui, temos acesso às funções no menu preenchido automaticamente Então, queremos ver se podemos aplicar isso ao alvo P. Então, se não pudermos aplicá-lo ao pré-alvo, vamos inverter isso. Portanto, se o item Doc não puder ser aplicado ao alvo P , removeremos o par de valores-chave. Então, quando fazemos as teclas de ponto, isso nos dá uma matriz. Portanto, essa matriz é separada do dicionário original , então acho que podemos realmente modificar esse dicionário sem problemas, porque já temos a matriz separada de chaves aqui. Então, esse loop aqui, se modificarmos o dicionário, não será um problema. Normalmente, você quer ter cuidado com isso. exemplo, você não deve modificar uma matriz enquanto está percorrendo ela, mas nesse caso, essa matriz é separada desse dicionário, então deve estar tudo bem No entanto, veremos com certeza quando realmente executaremos o código. Portanto, se não pudermos aplicar o item, queremos removê-lo da lista de opções porque não podemos usá-lo. Portanto, as opções restantes não removem ou facilitam, sim. Ok, aqui se chama apagar. E nós temos a chave ali mesmo. A chave é o item. Então, apagamos o item e isso o removerá como uma opção Então, depois de repetir todas as opções, já filtramos todas as que não podemos aplicar. Então, agora só precisamos fazer uma seleção com base no peso total e, depois de escolher cada um, nós o removemos das opções restantes. Portanto, nosso peso total aqui será uma flutuação igual a 0,0, e precisamos percorrer mais uma vez as opções restantes Então, poderíamos dizer que quatro pesos flutuam e os valores de pontos das opções restantes e, em seguida, dizemos que o peso total mais é igual a esse valores de pontos das opções restantes e, em seguida, dizemos que o peso total mais é igual Então eu acho que essa é uma maneira bem clara de escrever isso. Então, agora totalizamos o peso. Queremos fazer uma seleção aleatória entre zero e o peso total e depois ver qual deles escolhemos. Portanto, o peso aleatório de VR será inferido do tipo rand F vezes o peso total Então, fizemos isso algumas vezes no curso até agora. O peso total é nosso valor máximo. 0,0 é nosso valor mínimo. E considerando basicamente 0,0 a uma vez o peso total, obteremos algum valor entre zero e o peso total. Ok, agora temos nosso peso aleatório e queremos escolher um item entre as opções restantes. A propósito, haverá um loop aqui, mas podemos escrevê-lo primeiro para um item. Ok, agora aqui estão quatro opções nas opções restantes. Então, vamos dizer que se o peso atual é maior ou igual ao peso aleatório, então escolhemos essa opção. Então, agora precisamos, na verdade, de um peso atual aqui também. Portanto, nosso peso atual será um flutuador igual a 0,0 Então, primeiro, queremos adicionar o peso da opção. Então, atualmente, será mais igual às opções restantes nesta opção. Então, colocamos a chave do dicionário. Isso nos dá valor e , na verdade, pode ser uma maneira mais segura de fazer isso. Então, poderíamos dizer, escolha a opção. E se não houver opção, o valor padrão será nulo Nós nos daríamos um erro aqui. E talvez isso seja realmente o que queremos , porque esperamos que esteja lá. É muito importante se bloquearmos o par de valores-chave e ele simplesmente não existir. Então, sim, vamos deixar que seja exatamente como teria sido fazendo a opção de colchetes Efetivamente, é a mesma coisa exceto que essa função get permite que você aplique um backup padrão com uma vírgula e depois a variante padrão Portanto, é um pouco mais flexível, mas, neste caso, queremos uma falha grave se a opção simplesmente não existir, porque definitivamente deveria estar OK, então adicionamos o peso atual. Queremos verificar se o peso atual é maior que o peso aleatório. Portanto, se o peso atual for maior ou igual ao peso aleatório, adicionaremos isso à lista de opções selecionadas. Poderíamos simplesmente declarar as opções selecionadas aqui na parte superior Então var selected é uma matriz de itens porque é isso que precisamos retornar no final. Então, vamos acrescentar a opção à matriz selecionada Então, selecione a opção anexar e, em seguida, precisamos removê-la da lista de E, na verdade, acho que a forma como vou fazer isso é definir uma variável local aqui. Portanto, se nossa próxima seleção for um item igual a nulo, faremos com que o próximo seja selecionado Igual a essa opção e depois quebra. Então, saímos do circuito quatro. Não precisamos mais dos quatro circuitos. Depois desse loop, a próxima seleção não é igual a null. Em seguida, selecionaremos a opção de acrescentar pontos. Caso contrário, queremos sair de todo o nosso ciclo de quatro ciclos. Então, precisamos de um loop de quatro porque vamos fazer isso várias vezes. Então, vamos ver. Então, acho que aqui, 44 vezes nas opções Range, zero, CP, sublinhado pontuam Max Choices com incremento de um. Basicamente, isso significa que passamos de zero para o máximo de escolhas, subindo uma de cada vez. Quando atingimos o máximo de opções, paramos o ciclo. Então, se o máximo de opções for três, isso será executado três vezes. Vai ser zero, um, dois, e quando chegar a três, vai ser igual ao máximo de opções. Vou parar o circuito de quatro voltas. Ok, então basicamente pegamos tudo isso e o tabulamos, e agora ele vai repetir todo esse código, certo? Então, como parte da adição da opção, também queremos pegar o peso total, e queremos menos igual a qualquer que seja o peso da Então, diremos que as opções restantes não recebem opção. Estou ciente de que isso está chamando isso de novo, mas isso não é realmente um grande problema. Então, isso vai obter o valor flutuante do peso. Nós o removemos do peso total e depois queremos voltar aqui. Então, há também a outra possibilidade, que é que não há nada selecionado, o que significa que não há mais nada para selecionar. Então, poderíamos simplesmente sair mais cedo do circuito quatro. Então, estamos falando sobre isso para loop aqui. E isso provavelmente parece bom para mim. Só precisamos devolver o selecionado. Então, retorne selecionado. Então, no final disso, obtemos até três itens. Para cada um desses itens, queremos preencher a interface do usuário Então, digamos que a VR aqui em cima, as escolhas serão iguais para gerar escolhas nas opções P, e passamos o alvo P para que possamos comparar cada item em relação ao alvo para ter certeza de que é válido. Então, temos uma escolha aqui agora. E então queremos criar a cena de seleção de barbas e atribuir a escolha a ela aqui embaixo Como esse bit está, na verdade, fora desse loop de quatro, queremos acrescentar o próximo selecionado porque definimos o próximo selecionado aqui igual à opção para que possamos usá-lo fora do loop de quatro Então, queremos dizer o próximo selecionado aqui e também o próximo selecionado. Então, mais uma coisa que esqueci de fazer aqui é que, depois de ajustar o peso total, também esqueci de remover o próximo selecionado das opções restantes Então, diminuímos o peso total porque estamos removendo a opção e, em seguida, removemos a opção da lista real da qual estamos selecionando. Então, quando voltar aqui agora para os próximos quatro ciclos para as opções restantes, não terá essa opção lá, e simplesmente a ignorará completamente porque não está mais nesse dicionário, que é o que queremos Para as opções restantes, queremos apenas examinar o que ainda é uma seleção possível, agrupando as seleções que já foram 48. P47 - Seleção de recompensa por programação com propagação de sinal: Na nossa função Gerar opções, temos esse conjunto de opções. Na verdade, pode nos ajudar a declarar visualmente o tipo aqui, em vez de inferi-lo Então, como temos uma matriz, queremos percorrer a matriz. Então, para cada escolha, criamos uma instância de nossa cena de seleção de recompensas e, em seguida, aplicaremos a escolha a essa cena, basicamente definindo a escolha na cena e fazendo com que ela preencha sua subinterface com tudo o que precisamos Então, para escolher as opções, vamos criar uma seleção de recompensa, que atualmente é um controle, que será igual à cena de seleção de recompensa dot Instantiate Em seguida, precisamos adicioná-lo como filho a esse contêiner HBox. Portanto, adicione filho da seleção de recompensas. E então diremos o ponto de seleção de recompensa setHoce e passamos a Escolha Nossa seleção de recompensas, você pode ver aqui, atualmente não tem script. Essa função não existe, então precisamos criar uma função no script, e vamos fazer isso dentro da cena cheia. Então, queremos clicar em Abrir e editar. Então, entramos na cena original empacotada para esse elemento específico da interface do usuário. Então, na seleção de recompensas, queremos clicar em anexar um novo script e o chamaremos de Uilashrewardselection Crie isso. E do lado daqui. Daremos a ela o nome de classe Seleção de recompensas que facilitará preenchimento automático de suas funções E o que nos importa aqui é a escolha do conjunto de funções, e vamos passar uma escolha. E essa escolha é um item. Eu me lembro. Então, isso retornará vazio. E a partir daí, precisamos preencher todos esses elementos. Então, vou pegar o rótulo Rich Text e renomeá-lo para rótulo de nome Vamos renomear o texto direto para ícone reto. Vamos renomear o segundo rótulo de Rich Text para ser rótulo descritivo e vamos renomear o botão para ser botão Ok, isso deixará muito mais claro o que eles realmente devem fazer. Agora que temos essas configurações, vamos entrar no script de seleção de recompensas novamente no script de seleção de recompensas e obter uma referência para cada uma delas. Agora, do jeito que venho fazendo isso durante o curso, e acho que mesmo nesse caso, ainda prefiro fazer um at export var e diremos algo como name label. É um tipo do que quer que seja, rótulo de texto rico. Ok, e então você pode simplesmente atribuir isso ao inspetor. Sabemos como fazer isso, certo? Mas isso significa que sempre que você configura uma cópia do script, precisa definir manualmente as variáveis de exportação. Então, só para mostrar outra opção, você pode fazer em uma barra pronta, digamos, no ícone Rec que será uma textura reta E então você dá a ele um sinal ecológico e o configura no caminho de seu nome. Então, se eu disser escolher o botão, ele será preenchido automaticamente aqui. Podemos selecionar isso. E eu acho que isso precisa de um sinal de $1 no início. Então, contêiner de margem de cifrão, barra, contêiner VBox, barra, barra Agora, isso significa que, quando estiver pronto, ele obterá automaticamente esse caminho do nó e o atribuirá diretamente ao texto. Portanto, não precisamos configurá-lo manualmente no inspetor. No entanto, há uma grande falha aqui, que é que isso exige o caminho para aquele item seja o mesmo Portanto, se o seu botão de escolha for chamado de qualquer coisa , exceto botão de escolha, ele não o encontrará. Então, esse seria um dos motivos pelos quais eu poderia preferir fazer um at Export, porque se você reorganizar seus nós aqui, contanto que ainda tenha o conjunto de referência, isso não quebrará seu script Ok, é por isso que eu geralmente não uso isso, e vou voltar para o ícone Export var Rect, que será uma textura Rect E então queremos o rótulo de descrição Exportar var, que é um rótulo de texto rico aqui no botão de escolha Exportar var. É um botão. Ok, e para definir uma escolha, vamos devolver o passe por enquanto para que o script possa ser salvo e clicar em Seleção de recompensa. Vá para o canto superior direito e atribua cada um deles. Então, nomeie rótulo para rótulo de nome, ícone Rect para ícone Rec, descrição para rótulo de descrição E como temos dois rótulos em rich text, é aqui que ter nomes informativos, como rótulo de nome e rótulo de descrição realmente ajuda, em vez de serem chamados em rich text e rótulo em rich text two. Só quero ressaltar isso. E, finalmente, escolha o botão que atribuímos ao botão de escolha. Portanto, agora temos uma referência a todos eles e podemos preenchê-los facilmente com as informações do nosso item. Ok, agora, para lidar com a escolha do conjunto, podemos fazer o texto do ponto do rótulo do nome, e isso será igual ao nome do item. Então, no momento, nossa classe de item não tem um nome. A subclasse de item de arma tem uma definição, e essa definição tem um nome, mas podemos querer um nome específico para o item, e acho que essa seria a abordagem mais direta para criar um nome de item na classe do Então, se formos até o item, podemos fazer isso em Exportar nome de exibição do VR, que será um nome de string, e eu o padronizarei para item sem nome Então, isso é uma espécie de distinção entre o item e a definição da arma, porque um item nem sempre é necessariamente uma arma, então podemos distinguir aqueles com duas propriedades separadas, pelo menos por enquanto Então, agora vamos voltar à seleção de recompensas e escolher o nome de exibição de pontos da escolha Deixe-me dar uma olhada na definição do item de lança, e podemos ver aqui Portanto, a definição aqui está realmente configurada para ser mais uma definição da arma, de como ela sobe de nível e de seu valor de dano. Portanto, a descrição do item soa como algo que deveria ser separado, porque você pode pegar uma cópia desse item no mapa-múndi e dizer algo como: Ah, isso é um item de lança Isso adiciona a habilidade de ter a arma ao seu jogador, mas não é a definição da arma em si. Então, queremos distingui-los. Portanto, podemos dizer que o texto do ponto do rótulo de descrição será igual à descrição do ponto de escolha Agora precisamos que o item tenha uma descrição. Vamos copiar esse nome, clicar com o botão direito no item, símbolo de Lou E faremos em Export var, bem, e faremos em export var paste in description, que é uma string, e que estará em branco por padrão. Ok, agora na seleção de recompensas, isso é resolvido. Em seguida, queremos fazer o ícone Rect. Então, poderíamos dizer que a textura do ponto reto do ícone será igual ao ícone do ponto psíquico Mais uma vez, o item se distingue da definição de arma. Ele deve ter seu próprio ícone que possa ser definido. Então, vou exportar a textura do ícone VR. Ok, e temos o ícone de textura, para que possamos voltar à seleção de recompensas. Agora, eu quero ter cuidado aqui, porque se você tentar definir o ícone pchoict quando não houver um ícone de ponto pchoic, você receberá uma referência nula assim que tentar fazer referência Assim, você pode verificar manualmente se o ícone existe todas as vezes ou pode alterá-lo para ícone Pchoic dot Get e apenas ter essa segurança integrada Mas então temos que adicionar essa função à classe do item. Então, vamos clicar com o botão direito do mouse no símbolo e, em seguida, criarei nosso ícone da função G aqui embaixo , ícone da função G, e isso retornará uma textura ou nada. Então, se ícone, retornamos ícone, caso contrário, retornamos nulo. Está bem? Acho que é bastante simples. Esse método nos dá segurança caso seja nulo, então retornaremos null em vez de ter um erro imediato Então, o último é um pouco mais complicado aqui. Temos o botão de escolha. Quando o botão de escolha é pressionado, queremos fazer a seleção com a escolha. Então, queremos que o botão saiba sobre a escolha. E então passamos o sinal do botão sendo pressionado até nossa seleção de subida de nível, para que possamos aplicar o efeito ao jogador e fechar o menu. Então, aqui no nível de seleção de recompensas, queremos vincular o sinal do botão que está sendo pressionado à opção que passamos aqui, a escolha do item, e emitiremos isso como um sinal na seleção de recompensa, e então a seleção de subida de nível se conectará a ela subindo na cadeia e podemos basicamente saber nível superior, quando qualquer um dos nossos botões são pressionados e depois aplicamos os efeitos ao nosso player. Então, precisaremos fazer, digamos, o botão de escolha. Então, precisaremos escolher entre pressionar o ponto Connect e conectá-lo a uma nova função no Reward uma nova função no Mas vamos vinculá-lo à escolha P. Então, quando estamos vinculando, estamos basicamente passando um parâmetro extra para o retorno de chamada que essa função normalmente não teria Então, a função sublinhado na recompensa pressionada agora obtém a opção P, que é um item, e ela retornará nula, e agora podemos continuar passando essa escolha para cima na Assim, podemos ter um sinal de AR na parte superior, que dirá sinal selecionado, que passará uma escolha do item. Agora só precisamos emitir esse sinal, então selecionado. Dot I MIT, e passamos a opção P, e agora ela pode subir na hierarquia Então, sim, normalmente, o pressionamento de um botão não tem parâmetros quando você o recupera. Apenas informa que o botão foi pressionado. Mas, ao chamar bind, adicionamos esse parâmetro extra sempre que ele é pressionado Portanto, agora nosso botão pode nos fornecer informações muito críticas sobre qual escolha estava realmente sendo feita. Tecnicamente falando, também poderíamos definir a variável de escolha local aqui e, em seguida, pressionada, poderíamos simplesmente passar a escolha local para a escolha dos itens Então, se eu definir isso ao definir a escolha, isso também funcionaria. Duas maneiras de fazer a mesma coisa, mas agora você conhece uma maneira muito mais legal de usar a vinculação, então você pode realmente adicionar parâmetros extras Além disso, isso não exige a seleção de recompensas continue mantendo essa escolha, embora definitivamente pudesse, e não seria problemático aqui Ok, então vamos subir mais na hierarquia. Agora, em nossa seleção Lavop, que vamos ver. Temos o contêiner da caixa Rewards. Então, é aqui que estamos realmente criando as seleções de recompensas Então, aqui, eu preciso propagar o sinal para cima novamente. Então, digamos que sinal selecionado, que passará o item de escolha desse jeito. Portanto, sempre que preenchemos nosso menu de seleção de recompensas e agora que temos um nome de classe, podemos e devemos alterá-lo para seleção de recompensas E vamos conectar isso a uma recompensa selecionada. Então, aqui na parte inferior, criaremos esse sublinhado da função de retorno de chamada nas recompensas selecionadas Recebemos a Escolha P, que é o item que devolvemos vazio, e vamos propagá-la para Então, selecione o ponto EMT. Vamos emitir com a opção P. Então, isso sobe ainda mais na hierarquia agora. Então, isso está no nível do contêiner da nossa caixa de recompensas. Agora, na seleção de subida de nível, só precisamos nos conectar ao nosso contêiner de caixas de recompensas. Então, vamos exportar nosso contêiner de recompensas, que é um contêiner de caixa de recompensas. E quando estiver pronto, queremos nos conectar ao sinal. Recompensas: contêiner, ponto selecionado, conexão de pontos na recompensa selecionada. Função sublinhada na Recompensa, selecionada. Deixe-me ampliar um pouco aqui. E teremos nossa escolha P, que é o item, e retornaremos sem valor. Então, vamos passar por enquanto, e precisaremos aplicar o efeito ao jogador e fechar o menu. Voltaremos a isso em um segundo. Então, tivemos nosso método de seleção inicial. O que queremos fazer é basicamente redefinir o contêiner da caixa de recompensas. Queremos que ele seja preenchido, mas também queremos que ele limpe todos os itens existentes Então, no contêiner da caixa de recompensas, vou preencher fazer esse sublinhado e gerar escolhas Também vou fazer sublinhado para privado, para que não o chamemos acidentalmente de nossa interface principal Então, aqui precisamos sublinhar porque estamos fazendo com que o sublinhado gere escolhas Agora vamos criar a função que realmente vamos chamar. Então, opções de configuração de funções. Sim. Ok, isso faz algum sentido. E vamos passar nossas opções P, que são opções de nivelamento, e vamos passar o alvo P, que é nosso nó dois D. Claro, vamos preencher com essas opções e nosso Mas antes disso, eu também quero limpar esse menu. Portanto, qualquer uma das caixas secundárias, preciso removê-las antes de preencher ou preciso garantir que meu preenchimento reutilize a interface de usuário existente e, em seguida, as atualize com as novas Então, como teremos apenas algumas opções aqui, seria um pouco exagerado se preocupar demais em reutilizar todos os componentes possíveis da subinterface Portanto, a opção mais fácil de curto prazo seria definitivamente limpá-la, o que será para crianças e crianças. Vamos chamar Child Dot Q gratuitamente. Então, agora aqui no topo, podemos limpar antes de povoar. Ah, e precisamos concluir um tipo de retorno para as opções de configuração. Então, retornaremos vazios. OK. Sim. Então, agora, configure Escolhas, podemos chamar isso em nosso script de seleção de nível. Então, comece a seleção, faremos recompensas Container dot Start Selection, e isso passará para as Opções e o alvo, que é o player de contexto. E esse é o nome errado para o método. Na verdade, eram opções de configuração. Ok, então começamos a seleção. Nós configuramos as opções. Esperamos que o jogador basicamente escolha uma opção e, em seguida, receberemos nossa ligação de volta Então, nesse ponto, queremos fechar o menu. Então, poderíamos dizer que recompensa o container dot CE aqui. E eu fiz disso um método privado. Então, no contêiner da caixa de recompensas, vou apenas remover o sublinhado aqui e aqui Ok, agora ele é chamado internamente, mas também a partir de outros scripts Então, se você precisar tornar um método público, você pode fazer isso. Tecnicamente, mais uma vez, o GD Script não impede que você chame um método com um sublinhado É apenas a melhor prática para indicar a intenção. Então, de volta ao nível de seleção das recompensas selecionadas, queremos aplicar o efeito do item ao jogador. Diremos que p choice dot Try se aplica ao jogador. Então esse será o reprodutor de pontos de contexto. Em seguida, limpamos o recipiente e fechamos o menu. Ok, então vamos ver. Vamos nos esconder aqui. E isso pode ser praticamente tudo o que precisamos. Então, um pouco de limpeza aqui. Vamos até o contêiner da caixa Rewards e, bem, deixe-me mostrar as duas vistas em D, na verdade. Aqui você pode ver que temos essas três caixas aqui. É bom tê-los à vista aqui desde que os liberemos antes de começarmos a usar qualquer coisa. Então, se formos para o contêiner Rewards Box pronto, vou querer ligar para a Clear. Então, a função de sublinhado está pronta. Vamos esclarecer esses elementos da interface do usuário. significa que eles serão removidos e recriados sempre que o contêiner da Caixa de Recompensas aparecer Queremos que seja o mais otimizado possível Reutilizar cada componente da interface do usuário é melhor do que ter que recriá-lo a partir de uma instância Mas para algo simples como esse, você só vai mostrar uma vez a cada, sei lá, 30 segundos de jogo, que quase não deve ter nenhum impacto, e isso não é realmente um grande problema. Ok, então ainda temos a seleção de lanças aqui. Então, se realmente tentarmos subir de nível, devemos ver uma seleção. Definitivamente, é hora de fazer um teste e ver se realmente fazemos com que ele apareça e funcione. Então, vamos clicar em Play. E veremos como isso funciona. Ok, então parece que eu esqueci de colocar o contêiner de recompensas aqui na seleção de subida de nível Então, vamos aumentar o nível da seleção. Clique nisso. E na hierarquia, precisamos atribuir o contêiner de recompensas ao contêiner de recompensas Então essa é realmente a fraqueza das propriedades de exportação, certo? Se você esquecer de configurá-lo , não há realmente nenhuma indicação, ser que você encontrará erros em algum ponto do código. Portanto, não precisamos de uma declaração porque a conexão com o sinal já gerará um erro assim que falhar Vamos fechar e correremos novamente. Ok, então vamos pegar nosso item. Boom, temos apenas uma opção para escolher. Então, nomeamos o item aqui. Acho que simplesmente não defini um ícone ou descrição, mas você pode ver que o método Get icon, porque lidamos com o caso nulo, não vai nos dar um erro Por outro lado, se referenciarmos diretamente a propriedade do ícone de ponto porque era Null, isso geraria um erro aqui Se clicarmos em escolher, isso se aplicará ao jogador? Então, vamos descobrir mais sobre isso. Ele deve fechar o menu. Sim, mas esqueci de continuar o jogo. Portanto, temos que voltar aqui e garantir que, depois ocultarmos o menu ou talvez até mesmo antes de ocultarmos o menu, diremos que Geth dot paused é igual a false Vamos guardar isso e correr mais uma vez. Então, entramos aqui, fazemos nossa seleção, vamos escolher o item. Boom, já está lá. Agora, pareceu funcionar, mas o verdadeiro teste seria que, se tivéssemos uma tela para os níveis de nossos itens de arma aqui acima, trabalharemos nisso daqui a pouco. Por enquanto, a melhor coisa a fazer seria bater de perto e vamos até nosso item de lança Vou atingir o nível dois e vamos mudar o tempo de recarga para 0,1, porque isso será muito óbvio se passarmos para esse nível Então, vamos clicar em play novamente. Vou pegar nosso item, clicar em escolher e vemos que o tempo de recarga não é atualizado Então, algo está um pouco errado no código. Então, acho que o problema, na verdade estará na arma em si. Vou verificar aqui para ter certeza de que estamos realmente atribuindo o aumento de nível, então pare aí E deixe-me ver aqui, pronto, obtemos a definição de resfriamento para o cronômetro. Mas você pode ver aqui que estamos definindo a hora do cronômetro aqui Mas aposto que aqui embaixo, na verdade não redefinimos o cronômetro para um novo valor Então, sim, esse é um problema muito claro. Precisamos dizer o ponto do cronômetro. Na verdade, digamos que o início será o novo valor. Então, precisamos fazer o tempo de recarga do G. Precisamos obter o ponto de definição Obter o de recarga de um nível atual Então, definição, ponto Obtenha o tempo de recarga do nosso nível. Isso significa que sempre que reiniciamos o cronômetro, obtemos o tempo de recarga atual do Então, digamos que na metade do disparo de um projétil, mudamos nosso tempo de recarga porque nosso nível subiu Então, isso significa que na próxima vez que o projétil for lançado , reiniciaremos o cronômetro com nosso novo valor Então, agora ele usará a propriedade de nível dois. E acho que nem preciso ter esse ponto de interrupção. Tenho certeza que esse é o problema. Vamos continuar e clicar em Play. Vou pegar nossa arma, clicar em escolher e pronto. Basicamente, temos uma lança de metralhadora porque nossa lança atingiu o nível dois, e isso vai quebrar completamente o jogo Então, eu recomendaria que, no final, mudássemos a temperatura do nosso projétil de lança de volta para 0,9, agora que sabemos que funciona, e isso encerrará este vídeo 49. Ladrilho 48 Aplicando estatísticas de nível de arma ao gerador de projéteis e instâncias: Mostramos que podemos aprimorar nossas armas por meio da seleção de recompensas ao subir de nível, mas precisamos garantir que, ao aumentarmos o nível de nossas armas, estejamos usando todas as estatísticas corretas da arma, não apenas a redução do tempo de resfriamento. Então, vamos ver o roteiro do projétil. E veremos aqui dentro que ainda não estamos usando as estatísticas do nível da arma. Estamos usando uma velocidade embutida, e o dano final não é causado por nenhum cálculo. Está apenas passando 100 como variável local. Então, se você está percebendo a definição do nível da arma, ela ainda não está usando essas estatísticas, bem, é por isso Então, quando criamos o projétil, precisamos passar pelo nível da arma também Poderíamos ter uma função totalmente separada para fazer isso, mas acho que seria mais prático colocar as estatísticas do nível da arma na função de lançamento. Portanto, a função de lançamento serve não apenas para definir a direção, mas também para configurar as estatísticas específicas do projétil, mas o lançamento também serve para configurar as estatísticas específicas de lançamento desse projétil com base no nível atual da arma Então, como perímetro extra, vamos querer passar no nível P, que é o nível da arma Então, essas serão todas as estatísticas que precisamos trazer aqui. E em vez de no topo ter uma velocidade aqui, vou remover e , em vez disso, vamos dizer var nível do tipo de nível de arma, e é daí que vamos extrair todas as estatísticas. Então, quando estivermos fazendo o processo de física e precisarmos multiplicar pela velocidade, faremos o nível Velocidade do ponto. OK. Vamos adicionar isso. E agora, no lançamento, precisamos definir o nível igual ao nível P. Ok, então é assim que obtemos as estatísticas, e então só precisamos atualizar nossas chamadas para o lançamento. Mas há outras informações aqui que são relevantes. Então, primeiro, quando a caixa de acerto atinge uma caixa rt, precisamos retirar o dano das estatísticas de nível. Então, aqui precisamos de um cálculo de dano aleatório entre dano causado por nossos homens pela arma e nosso dano MÁXIMO. Então, removerei essa linha e diremos que var damage será um número inteiro, e isso será igual a um intervalo inteiro aleatório entre o dano mínimo e o dano máximo Então, nivele o ponto de dano mínimo e, em seguida, nivele o ponto máximo de dano que lida com a aleatoriedade aqui. Então temos nosso dano final. Vou apenas dizer que é igual ao dano agora, e então passamos nosso dano final para a caixa Hurt. Portanto, agora também temos danos aleatórios com base no nível e na velocidade definidos pelo nível. Então, se olharmos para o script da arma dois D agora, obteremos um erro lançamento do ponto de projétil porque precisamos no lançamento do ponto de projétil porque precisamos passar para o nível atual da arma dois D, que está convenientemente configurado aqui na arma dois D. Então, digamos coma, nível da arma aqui, e isso apenas o envia do nível da arma para a instância do projétil Então, podemos testar essas mudanças executando o jogo agora. Então, vamos encontrar nosso inimigo onde quer que eles queiram desovar Ok, tem um. E você verá que temos danos aleatórios entre nossos homens e MAX. Atualmente, você pode ver que ele ainda está passando pelo inimigo, aí está nossa subida de nível. Então, em teoria, isso deveria ser um pouco mais rápido, tanto no resfriamento quanto nos danos. Você pode ver os danos lá em cima. Então, na maioria das vezes, isso parece estar funcionando. Mas ainda há algumas coisas que precisamos ajustar, como quantos golpes ele pode fazer antes de realmente excluir o projétil Então, no hipbox hit, na verdade, queremos aumentar quantos golpes fizemos e, se os acertos forem iguais aos nossos golpes MAX ou maiores , queremos liberar nosso Então, aqui no topo, teremos um número variável, e isso será um número inteiro Vai começar do zero. E toda vez que alcançamos o sucesso. Vou começar aqui e dizer que var hit igual a P hurt Box dot Tri E então diremos, eu acerto, depois acerto mais é igual E então também podemos dizer que se os acertos forem maiores ou iguais ao nível máximo de acertos, então vamos liberar nosso projétil Então, agora isso pode ser liberado se o cronômetro expirar para basicamente persistir na cena do jogo, que precisamos substituir pela variável aqui também, aliás . Ou se os golpes atingirem o máximo de acertos , ele também será liberado imediatamente. Então, aqui em cima, também queremos dizer que quando criamos o cronômetro, vamos pegar a propriedade do nível Então dizemos nível, e acho que ainda não o definimos . Então, precisamos, tipo, de uma duração. Vamos criar uma estatística de duração para nossa arma. Ok, então nivele a duração dos pontos. Isso significa que precisamos pular para o nível da arma. Procure o símbolo e vamos criar a duração aqui embaixo. Diremos que na exportação var a duração será uma flutuação igual a, digamos, 5 segundos por padrão Então, esse é o número máximo de tempo que o projétil pode persistir no mundo do jogo antes da remoção, supondo que ele não seja removido por algo como atingir ou exceder o número máximo de acertos Ok, então vamos continuar e apertar play mais uma vez. Então eu vou clicar em play. Aqui está nosso projétil de lança, vamos esperar que alguns inimigos apareçam vamos esperar que alguns inimigos apareçam . Está bem? Então nós temos isso. E você pode ver, muito importante, que assim que um cara é atingido, a lança se remove sozinha Então, essa é uma grande mudança. E se subirmos de nível até o nível dois, ainda deve ser o mesmo, mas nosso dano aumenta. E vamos tentar observar esse projétil, e ele desaparecerá após 5 segundos. Então 45. Ok, aí você pode ver os projéteis desaparecendo do mundo do jogo Isso é muito importante porque, caso contrário, eles podem nunca ser removidos e estariam apenas consumindo recursos do sistema sem motivo. Portanto, queremos que eles sejam removidos automaticamente eventualmente. Ok, agora também há algumas outras propriedades do nosso nível de arma, o atraso na geração, o deslocamento de alcance e os projéteis Portanto, precisamos garantir que, em nossa arma para D, estamos realmente gerando projéteis extras, gerando-os em relação ao deslocamento e que quaisquer projéteis adicionais tenham um atraso após o lançamento do primeiro E então, com o atraso de amplitude, qualquer projétil após o primeiro tem um atraso antes de ser gerado Ok, então vamos às armas para D. Então, cada vez que lançamos, precisamos que os projéteis apareçam Portanto, precisamos de um índice de quatro voltas, digamos, quatro no intervalo zero até o nível da arma. Ponha projéteis e, em seguida, incrementaremos em um. Então, vamos repetir isso algumas vezes. Depois que cada projétil for lançado, aguardaremos o cronômetro de criação do Kit tree Create e precisaremos desse ponto de nível de arma, Span Delay OK. E então vamos esperar pelo tempo limite. Então, após o primeiro loop, esperamos que o curto intervalo de tempo atinja o tempo limite antes de criarmos nossa segunda instância de um projétil por lançamento, e estamos criando projéteis com base na quantidade de projéteis que o nível da arma Mais tarde, se quiséssemos, também poderíamos misturar isso com, digamos, um bônus do jogador. Portanto, se o jogador tiver mais um projétil para todas as armas , temos a função de somar esses dois números para obter o número total de projéteis aqui Então, finalmente, precisamos gerar um deslocamento aleatório com base na distância de deslocamento do nível da nossa arma Então, para nosso deslocamento, será igual a um vetor dois, e então faremos um intervalo F aleatório para X e Y. Então, intervalo F aleatório, menos 1,0 a 1,0, e então intervalo F aleatório, aleatório, menos 1,0 a 1,0 E multiplicamos isso pelo nível da arma. Deslocamento de pontos Então, isso nos dará um valor aleatório entre a distância máxima negativa no deslocamento do vão e, em seguida, o deslocamento máximo positivo aqui para o X, e o mesmo para o Y e o Y positivo. Então, tecnicamente, isso dará uma forma quadrada porque o X e o Y não afetam um ao outro, então pode ser menos 1,0 em X e Y ou 1,0 positivo . Eu acho que está tudo bem. Estamos apenas tentando fazer uma compensação simples. Na verdade, não importa muito se é um quadrado ou círculo, a menos que você queira que isso importe. Então, vou descer até o projétil e adicionar o deslocamento OK. E isso fará com que, sempre que gerarmos o projétil, ele tenha algum deslocamento se tivermos esse conjunto na arma Então, se eu olhar para o item da lança, bem, podemos ver que aqui não temos nenhum deslocamento de envergadura Então, talvez queiramos definir um. Vamos ver. Qual seria o deslocamento máximo de pixels que eu gostaria de fazer? Talvez umas cinco. E então faremos apenas cinco para todos eles. Então, abra cada nível de arma e faremos cinco. Então isso pode ser positivo ou menos cinco ou qualquer coisa intermediária para X e Y. E então eu vou correr, e vamos ver como isso Então observe onde as lanças estão surgindo. E você pode ver que eles estão um pouco afastados um do outro, certo? Portanto, não está sempre estritamente na mesma posição. E também o torna um pouco mais interessante para algumas variações. Ok, agora, o que eu quero fazer é pegar a arma de nível um para testar, e vamos chegar a três projéteis, e eu vou fazer essa escravidão 0,05 segundos, que Então, vamos jogar e executá-lo, e devemos obter uma cadeia de três projéteis Um, dois, três, um, dois, três, um, dois, três. Então você pode ver aqui um, dois, três. Ah, agora, um pequeno problema aqui, você pode ver que se eu girar após o lançamento do primeiro projétil, os outros projéteis eu também giro quando eles são instanciados Ok, então para essa rotação Rads, eu quero calcular isso fora do circuito de quatro Eu só quero fazer isso uma vez. Assim que o primeiro projétil for lançado, todos os outros devem ser bloqueados nessa direção Então, vamos continuar e clicar em Play. E agora, se eu me mover, mas girar, você verá que todos os três estão sempre indo na mesma direção, o geralmente é o que você quer, eu acho Então, vamos remover os projéteis extras Primeiro, podemos manter esse deslocamento de desova personalizado para todos eles Se você quiser, podemos até definir que uma arma padrão tenha um deslocamento de alcance, mas isso depende de você se quiser voltar e personalizar os padrões de nível de arma Deixe-me dar uma olhada no script do nível da arma mais uma vez e ver se resolvemos tudo Portanto, dano mínimo, dano máximo, velocidade, projéteis de resfriamento, máximo de acertos, deslocamento, atraso e Sim, estamos usando todas as variáveis do nosso nível de arma, e isso nos dá bastante personalização para qualquer uma das armas que queremos criar 50. P49 Construindo uma arma giratória: Neste ponto, como temos um sistema de subida de nível em funcionamento, queremos pegá-lo e adicionar opções extras a ele. Então, agora seria o momento perfeito para adicionar uma segunda arma ao nosso jogo. Então, isso será semelhante ao primeiro. Adicionaremos uma foice, e a foice poderá girar ao redor da tela vez de seguir em frente, como a lança Então, se abrirmos o Spear Dot TSC e as armas, você pode ver que ele já tem a maioria dos componentes que precisaremos para nosso Então, vou duplicar essa cena no canto inferior direito clicando com o botão direito do mouse na cena e duplicando Então, vamos colocar Syth aqui no ponto TSCN. Ok, agora eu posso pesquisar Syth no projeto e abri-lo. Vamos ampliar o centro. Algumas das coisas óbvias que queremos mudar primeiro, o nome do projétil, então vamos chamá-lo de Syth E então o sprite deve ser selecionado a partir da textura do atlas para o sprite da foice Então, vou clicar aqui, expandir a arte e usaremos os mesmos sprites de madeira Então, se bem me lembro, há um bom Syth aqui que podemos usar. Então, vamos selecionar isso e clicar em Fechar. Agora você pode ver que a caixa de acerto não faz mais sentido porque tem essa curva aqui. Então, queremos clicar em nossa forma de colisão, e eu vou puxá-la aqui e depois expandi-la para a direita, algo assim, ou poderia até torná-la mais parecida com um quadrado retangular, se eu quiser cobrir toda a borda da lâmina Então, vamos fazer isso. Agora, se instanciarmos esse projétil, ele ainda funcionará quase exatamente como a lança, onde simplesmente avançará Então, o que realmente queríamos fazer é girar em torno do ponto central Então isso vai significar que precisamos de um deslocamento, e precisamos girar esse deslocamento em um círculo e isso nos dará nossa Então, vamos clicar com o botão direito do mouse no site. Vou adicionar um novo nó dois D, e então esse nó dois D será o pai do Sprite e da caixa de sucesso Então, vamos colocá-los aqui embaixo. E então eu vou renomear isso para Rotator two D, e vamos clicar com o botão direito do mouse e anexar um script a Então, as armas Rotator two D estão bem. Vamos criar isso, vamos dar a ela o nome de classe rotator two D e, em seguida, queremos colocar algumas propriedades aqui Então, vamos dar uma velocidade para esse nó rotador. Portanto, lembre-se de que esse rotador é filho do objeto base. Então, o objeto base terá seu próprio movimento e, em seguida, esse subobjeto controlará especificamente a rotação Então, os dois se movem ao mesmo tempo, mas são independentes um do outro. Então, na exportação var velocity, que é um vetor dois, terei esse padrão de dez pixels à direita e zero no eixo Y. Então, isso afetará o movimento na tela. Mas também queremos que o nó gire fisicamente, então parece que nosso site está girando Então, ao exportar em graus de velocidade de rotação, isso será um fluxo, eu o padronizarei para 360, o que significaria uma rotação por segundo neste caso. E então só precisamos atualizá-lo no processo ou no processo físico. Vou fazer o processo de física para ser consistente com outros movimentos do jogo. Então, digamos que nossa quantidade será igual a graus de brilho. Então, vamos converter esses graus de velocidade de rotação uma quantidade de brilho. Então, precisamos dos graus de velocidade de rotação multiplicados pelo Delta para obter a quantidade de rotação desde a última atualização do quadro e, em seguida, vamos girar por essa quantidade Então, podemos até mesmo chamar essa quantidade RDs se quisermos deixar claro que é uma quantidade de brilho e eu também a farei flutuar, apenas para dar o máximo de clareza possível Ok, então precisamos mover fisicamente o nodo, e isso será baseado em nossa velocidade aqui em cima Então, vou dizer que nosso movimento será igual à velocidade vezes Delta E então chamamos de translate a quantidade de movimento, e esse é essencialmente nosso script rotador Então, se você precisar personalizar quaisquer valores, você tem o inspetor aqui para atribuí-los. Então, agora queremos criar uma arma dois D que possa instanciar nossa mira. Então, vamos procurar a arma de lança se ao menos a salvarmos no projeto Então, agora vamos procurar a arma de lança. Nós vamos abrir isso. Vamos dar uma pequena olhada aqui. Portanto, esses são os dois nós D com um reprodutor AudioStream que reproduz o som de barra quando instalamos uma arma Então, eu quero duplicar isso e, em seguida, criar uma definição Syth para nossa arma Então, vamos duplicar a cena da arma de lança como arma Syth. Então, vamos procurar Syth novamente. Clique duas vezes em Open Syth, renomeie a arma de lança para arma E então, à direita, precisamos criar uma nova definição. Então, vou ampliar aqui, uma nova definição de arma, e essa será Syth. Nosso ícone, podemos simplesmente copiar do projétil Syth real Então, vou para a cena do Syth e depois clicamos no sprite e clicamos com o botão direito do mouse na textura, copiamos, vamos até a arma da foice e colamos no ícone com o botão copiamos, vamos até a arma da foice direito do mouse em Colar Ok, agora precisamos definir alguns níveis de armas aqui. Então, vamos criar nosso conjunto. Começaremos com o nível um da arma, novo nível de arma. Então, como queremos que nossa foice funcione? Talvez a foice se mova mais devagar do que um projétil normal. Talvez o resfriamento seja mais longo, então poderíamos dizer que cerca de 1,5. Antes de Max atingir, vou colocar em cinco, para que a foice possa atingir muitos alvos antes de morrer. Em caso de danos, vamos também aumentá-lo para 20 a 30. E um projétil. Ok, então vamos adicionar esse par de valores-chave e, em seguida, vamos fazer o nível dois com um novo nível de arma. Expanda o nível um da arma para que eu possa comparar. E então eu vou causar, digamos, 30 a 40 de dano, velocidade de 55, resfriamento de 1,4. Máximo de acertos de seis, e eu adicionarei esse par de valores-chave. Vamos fazer o nível três, e assim por diante, que você quiser fazer os números. Ok, então aqui estão os números que eu usei no nível três da arma. Você pode pausar se quiser copiar. Aqui temos arma de nível quatro, arma de nível cinco. E arma de nível seis. E acho que isso deve ser suficiente por enquanto. Ok, então, se bem me lembro, ainda não defini na definição de arma a habilidade de escolher sua cena lotada. Então, na definição da arma, eu quero adicionar uma opção G vista. Então, por enquanto, vamos padronizá-la para uma variável de exportação. Então, eu vou dizer que exporte uma cena de VR, e essa será uma cena lotada. Ok, e então, em vez de Getsn carregar a lança, queremos retornar a cena Então, como estamos usando um método get seen, podemos posteriormente entrar e alterar se houver algumas cenas extras que queiramos considerar transmitir, em vez do padrão básico. Mas isso deve ser bom por enquanto, mas realmente não precisamos de uma segunda cena no momento. Ok, agora só precisamos ter certeza de que, na definição da foice, carregamos rapidamente a foice E então na definição da lança, então pesquise a definição da lança. Você clica duas vezes nele. E então precisamos carregar rapidamente a cena da lança. Ok, e isso deve ser bom lá. Acho que a última coisa que precisamos para nosso Syth é o item Syth. Agora queremos encontrar o item Spear em nosso projeto, duplicá-lo e criar um item Syth Então, pesquise o item Syth. E esse item Syth que vamos atribuir, é claro, a definição de foice Agora, para que nossos Sites sejam adicionados como uma arma para nosso jogador, precisaremos de uma referência à arma 2 D. Que podemos adicionar ao equipamento do nosso jogador porque ainda não existe no jogador, então ela precisa ser Ok, então, para adicionar nossa referência à cena da arma, não podemos realmente usar a cena do pacto porque, se fizermos isso, ela terá uma referência cíclica porque a arma TD já faz referência a esse recurso de definição de arma Então, neste caso, para contornar isso, precisamos fazer um arquivo de exportação, estará entre aspas, ponto estrela TSCn, que significa que podemos filtrá-lo por qualquer coisa que tenha a extensão dot TSCN no final E vamos dizer var weapon two D path, e isso será uma corda. Este é o caminho para a cena de armas para adicionar dois carregamentos de armas, como o jogador Ok, agora, se olharmos nossa definição de lança, podemos atribuir à arma dois caminhos D, que serão em armas, e então temos a arma de lança aqui, Então é disso que precisamos. E então precisamos fazer a mesma coisa com a foice Então, procure a foice. E parece que eu a chamei de arma de foice, mas essa deveria ser a definição do site aqui embaixo O TRES é a definição. A cena é a arma do local. Ok, então clique duas vezes na definição do site e atribua o caminho a ela. Então, na verdade, você pode simplesmente arrastar e soltar daqui para lá, e isso o atribuirá. Portanto, no item de arma atual, se o equipamento ainda não tiver a arma , precisamos realmente adicionar a nova arma no nível um ao carregamento , precisamos realmente adicionar a nova arma no nível um ao Em vez de retornar falso aqui e aplicar três vezes, na verdade vamos criar a nova arma Então, podemos dizer que a arma será igual a. Vamos dar uma olhada em nossa arma de definição do caminho D, queremos instanciar Então, vamos dizer carregar no caminho e, em seguida, instanciar E essa vai ser a nossa arma. Então, precisamos adicionar isso ao carregamento. Então, carregue Adicione a arma e nós vamos adicionar a arma. Se isso funcionar, queremos voltar a ser verdade. Portanto, se tivermos nosso item, agora podemos adicioná-lo à lista de itens possíveis para nossa interface de recompensa gerar. Então, se eu clicar na cena de seleção de subida de nível e formos para o primeiro nó aqui à direita, temos nossas opções de nivelamento de nível um e já adicionamos o item Spira Então, vamos adicionar o item do site. Então, carregue rapidamente o item do nosso site, atribua um peso de um e adicione-o. Ok. E então vamos clicar em Play e ver o que acontece quando vamos até aqui. Então você pode ver que diz item sem nome, e nós realmente não vemos nenhum detalhe Se eu clicar em escolher, na verdade não está lançando o novo projétil Portanto, ainda temos algum trabalho a fazer para isso, personalizando os itens e garantindo que eles sejam carregados corretamente, e trataremos disso na próxima parte 51. Ladrilho 50 Criando uma interface de usuário de exibição de armas para inventário de jogos: projeto realmente precisa agora é a capacidade de ver quais armas equipamos no canto superior esquerdo com o indicador de interface do usuário. E quando subimos de nível para atualizar a primeira arma ou escolher uma nova arma, eu também conheço esses nomes e descrições aqui Isso também aparecerá aqui para que possamos associar o que deveríamos estar vendo e o que estamos realmente vendo. Então, isso nos ajudará na depuração, mas também é muito útil para o jogador Então, vamos criar uma nova cena de interface de usuário, então vou clicar em Mais aqui. Então, eu quero nomear esse nó de controle para, digamos, exibir armas e também clicar com o botão direito do mouse e mudar seu tipo para um contêiner de painel. Ok, isso nos dará um plano de fundo por padrão. Então, dentro daqui, vou querer um contêiner de margem e, em seguida, continuar com o contêiner HBox para organização Então, clique com o botão direito do mouse em Adicionar um contêiner de margem e, em seguida, clique com o botão direito em Adicionar um contêiner HBox Ok, e aqui vamos colocar basicamente um ícone com um indicador de nível para cada uma de nossas armas da esquerda para a direita. Vamos pegar a tela de armas e reduzi-la para ficar muito mais parecida com esta E então eu vou salvá-lo nosso projeto na pasta UI, então na pasta UI, as armas são exibidas. E vamos colocar uma cópia em nossa tela de interface de jogo possamos ver como isso vai ficar mais ou menos. Então, procure a arma e, em seguida, vamos pegar a tela das armas e posicioná-la sob a interface do usuário. E podemos ver que é bem grande lá. Então você pode clicar aqui e entrar na tela de armas, e vamos reduzi-la para talvez mais no meio da tela Observe a caixa azul indicando o tamanho total da nossa interface do usuário. Então, isso vai precisar ser um pouco menor, na verdade. E eu provavelmente também quero me deslocar do centro. Vamos também fazer o centro de layout por padrão. Agora podemos voltar à jogabilidade UI Canvas. Podemos ver nossas armas exibidas lá. Na verdade, não está aparecendo como esperávamos. Então, na exibição de armas, vou usar as âncoras predefinidas e vamos usar o centro por padrão ou o centro superior, e vamos usar o centro por padrão ou o centro superior, em vez disso. Então, no centro da parte superior. E podemos ver o problema de por que ele se reduziu a nada Então, vou usar o tamanho mínimo personalizado aqui e definir um padrão. Vou dizer 200 para o X e depois 50 para o Y. Isso é só para que possamos ver e ajustar na nossa interface de jogo Então, vou passar para a jogabilidade UI Canvas, e agora podemos posicioná-la onde precisarmos. Então, vou posicioná-la, digamos, aqui à direita da nossa barra de saúde principal e da barra EXB, e vou arrastá-la assim Ok. E então podemos exibir alguns ícones de nossos níveis de armas. Então, para saber mais sobre isso, vamos querer usar nosso contexto de jogador para que possamos mostrar quais armas o jogador tem. Então, na exibição de armas, vamos adicionar um script islas weapons display dot GD E então vamos querer exportar var o contexto, que é o contexto do jogador aqui, e podemos atribuí-lo no inspetor Então, carregue rapidamente o contexto do player. E quando estiver pronto, vamos querer usar isso para obter referência ao nosso carregamento de armas Então, a função underscore está pronta, ela retornará void e, em seguida, diremos context dot player dot Temos uma referência ao carregamento? Nós não temos. Então, se não quisermos criar outra propriedade embutida do player e fazer com que ela seja diretamente referenciada no script do player para ajustá-la, poderíamos dizer find children, e o padrão será composto por aspas vazias O tipo será o carregamento de armas. Então, isso vai nos dar uma matriz. Vamos obter o primeiro resultado disso fazendo colchetes em um zero, que significa índice de matriz de zero E vamos atribuir isso a um carregamento. Portanto, nosso carregamento de sublinhado será um carregamento de armas E vamos dizer que o carregamento de sublinhado é igual ao resultado disso e queremos afirmar que isso não é nulo Portanto, assert underscore loadout não é igual a nulo. É preciso ter uma carga no jogador para mostrar para exibição das armas, nome percentual no final para que possamos obter o nome desse nodo E então queremos que as armas do nome da classe apareçam aqui no topo. Isso exibirá as armas e os níveis do personagem de contexto. Então, vamos fazer outro em Export var. Isso será para o UIC. Vamos dar exemplos para cada uma das armas em nosso equipamento Então faça um em Export var. Digamos que a exibição de armas, que será do tipo exibição de armas, mas ainda não a criamos. E para indicar que essa tela também faz mais do que apenas mostrar os dados, mas também conecta tudo Na verdade, vou renomear isso para ver. Isso também ajudará a diferenciar da exibição de armas, o contêiner de subinterface do E então eu vou renomear ambas as telas de armas. E então eu vou renomear as duas armas, ponto GD, e TSCN e Então, agora será Weapons View e aqui em cima, armamentos view dot TSCN Ok. Além disso, entre na cena de visualização e renomeie o nó raiz Isso é muito importante. Então, as armas são vistas lá. Agora, precisamos criar nossa exibição individual de armas para que ela possa entrar na visualização das armas. Então, vamos adicionar uma nova interface de usuário ao nosso jogo. Essa será uma interface de usuário no início. E estou pensando que a raiz aqui também pode ser que seja um contêiner de painel. Você sempre pode deixar um painel vazio, mas ter a capacidade de ter o plano de fundo é meio útil. Então, vamos mudar isso para um contêiner de painel. Vou renomear a raiz para ser exibição de armas. Vamos clicar com o botão direito do mouse nele, adicionar um contêiner de margem do nó filho, caso seja necessário, e clicar com o botão direito do mouse em Adicionar um wect de textura para exibir nosso ícone Clique com o botão direito do mouse em adicionar uma etiqueta. E, na verdade, estou pensando que não preciso um contêiner VBox ou HBox para isso, porque talvez eu queira que o rótulo escreva sobre a textura Para muitos jogos que tinham uma textura e depois texto ao mesmo tempo, ele realmente escreveria o texto sobre o ícone da textura. Você veria muito isso nos sistemas de inventário em relação ao número de itens no inventário. Exceto neste caso, estamos falando sobre o nível da arma que está equipada para o jogador. Então, como texto de teste, poderíamos dizer o nível X aqui. Obviamente, podemos ver que a tela está ocupando a tela inteira agora. Então, vamos realmente reduzir isso. Vou até a exibição da arma básica e levaremos o layout para as âncoras predefinidas no canto superior esquerdo Ok, isso deve reduzi-lo drasticamente. Agora podemos ver que está apenas mostrando o texto. Vamos definir uma textura nesse reto de textura. Então, farei uma nova textura de atlas e, em seguida, carregaremos rapidamente um atlas Vamos procurar talvez o 16 por 16. Folha Sprite em nosso jogo para todos os ícones e, em seguida, queremos editar a região e selecionar uma Então, algo que parece uma arma. Aqui temos uma espada que funciona bem e podemos fechar. Ok, podemos ver que o ícone da espada está lá, mas não respeita a proporção, então queremos ir para o modo de alongamento e mudar isso para manter o aspecto centralizado, eu acho Ok, aí está. E agora queremos pegar nosso contêiner principal de exibição de armas, e queremos que ele também tenha um tamanho específico. Então, vou dizer tamanho mínimo personalizado de 48 por 48. Isso nos dará um quadrado aqui. E eu vou querer pegar o texto do rótulo, e nós queremos que ele seja centralizado na parte inferior Então, o alinhamento vertical na parte inferior, aqui no, você verá que isso não muda nada, porque precisamos expandir o tamanho da etiqueta para que o texto seja centralizado na parte Então vá para o layout agora, e nós vamos querer o tamanho do contêiner para preencher, eu acredito Sim. Ok, aí. Então, agora ele vai mostrar o nível X no canto inferior direito. E agora parece que queremos um pouco de amortecimento entre nosso reto de textura e nosso rótulo Por enquanto, vamos salvar isso em nossa pasta de interface de usuário, nossa tela de armas. E acho que o que queremos é um segundo contêiner de margem. Então, vou clicar no primeiro contêiner de margem, adicionar outro contêiner de margem, e esse será o pai da texturização Então, vamos posicionar isso no topo novamente para que o texto apareça. Agora, com esse contêiner de margem, acesse as substituições de tema e queremos que a margem inferior tenha algo em torno de dez pixels Dessa forma, o texto não mostrará que você sabe, sobre as partes importantes do nosso ícone. Talvez até precisemos mais do que isso. Então, vamos tentar 12. Talvez até precisemos mais do que isso, na verdade. Para que possamos ver como ficará mais adequadamente, vamos aplicar o tema do nosso jogo à tela da arma. Então, clique na exibição da arma, encontre o tema e carregue rapidamente nosso tema atual. Ok, agora isso é muito menor e está no canto inferior esquerdo. Acho que quero isso no canto inferior direito. Então clique na etiqueta e vamos fazer o alinhamento horizontal para a direita Está bem? Parece muito bom, mas está um pouco perto da borda. Então, eu quero pegar o contêiner de margem principal. Essa é a que está logo abaixo da tela da arma, e eu quero definir algumas margens Então, vamos às substituições de temas e talvez dois pixels em cada uma delas Ok, isso parece certo. Exceto talvez a parte inferior da margem. Talvez não precisemos disso. Sim. Ok. Eu gosto mais disso. Tudo bem, agora, nossa tela de armas precisará uma referência ao nodo D da arma 2 E então, sempre que os dois nós D da arma sobem de nível, mudamos o texto aqui para mostrar o novo nível. Então, vamos adicionar um script à exibição da arma. Isso só vai aparecer no ponto de exibição GD do Uilashwapon. Ok. E esta será a exibição da arma com o nome da classe. E precisamos de uma referência à arma 2 D. Eu poderia simplesmente exportá-la agora. Então, essa será uma arma var do tipo arma dois D. Eu direi que valor definido, e essa será arma igual Sempre que configurarmos a arma, acho que vou simplesmente chamar uma função de atualização, e vamos configurá-la aqui Então, atualize a função. Portanto, para definir o texto no rótulo e no ícone, precisamos obter uma referência de exportação para cada um deles. Então, em Export var texture, texto direto do tipo textura Rc E então precisamos em Export var label, que é do tipo label. E quando atualizamos, queremos dizer que a textura de pontos texrec será igual ao ícone de ponto definição de pontos da arma. Sim, isso funciona E então diremos que o texto do ponto do rótulo é igual ao ponto da arma, se tivermos um nome aqui, nome da arma. Não, queremos o nome da definição porque o nome na arma é, na verdade, o nome do nó que não terá espaços ou algo parecido, então é melhor obter o nome do recurso porque essa é uma propriedade personalizada que definimos. E então queremos dizer que mais é igual a espaço mais uma sequência do nível de pontos da arma. Está bem? Então, isso basicamente mostrará o nome da arma e, em seguida, em que nível ela está atualmente. E caso a definição da arma não tenha um ícone, vamos criar um método de obtenção de ícones. O que funcionará como fizemos com um dos outros scripts anteriores, que retornará null se essa propriedade não for definida Então, vamos clicar com o botão direito na definição. Vamos abordar isso, clique com o botão direito do mouse na definição da arma. Vamos abordar isso. E então vamos criar nosso ícone de função G, que retornará uma textura dois D. Então, se o ícone não for igual a nulo, retornaremos o ícone Caso contrário, retornaremos null, e isso deve evitar que você receba erros se o ícone for nulo Ok, e provavelmente também queremos tentar atualizar o R para que o sublinhado da função esteja pronto, vou tentar fazer uma Isso também nos ajudará a confirmar que, se não houver uma arma com dois conjuntos D, ela funcionará bem e aparecerá em branco. A ideia aqui é que sempre que configurarmos a visualização de armas, ela seja preenchida com exibições de armas Configuramos a arma e ela será atualizada imediatamente Então, vamos para a visualização de armas. E aqui dentro, bem, você vê que eu estava exportando uma tela de armas, mas na verdade, o que eu quero fazer é exportar a cena Então, essa será uma cena lotada que podemos exemplificar. E então carregamos rapidamente à direita nossa tela para a arma, então exibição da arma. Então, pronto, quando tivermos o carregamento, quero preenchê-lo com todas as exibições de armas de cada uma das armas que estão realmente em nosso Então, fiz algo semelhante com o nível de seleção, em que eu apenas o limpo e o reinicio a cada vez, gerando novas cenas para gerando novas cenas para cada subinterface que precisa ser criada Mas aqui, na verdade, vou tentar reutilizá-lo que vocês possam ver as duas abordagens Tecnicamente, esse seria o melhor uso de seus nós, pois não precisaria excluí-los e recriá-los a cada vez. Então, acho que será útil saber depois do curso. Então, uma das maneiras pelas quais podemos acessar facilmente todas as nossas telas de armas ativas será ter uma variedade delas. Então, eu vou dizer que var underscore é exibido, e isso é uma matriz Vou ampliar a exibição das armas. Vamos também criar nossa função de atualização. Portanto, nossa atualização de função retornará nula. E para cada uma das armas em nosso conjunto de armas, criaremos uma tela, caso seja necessário criar uma Caso contrário, se ela já existir nessa variedade de exibição de armas , vou reutilizá-la apenas atualizando as propriedades dela com a nova arma configurando a arma na arma Ok, então, para nossa função de atualização, queremos percorrer todas as armas, e faremos isso usando as posições do índice para que possamos combinar os índices de carregamento de armas com nossos índices de exibição de Portanto, para IN, alcance zero para sublinhar o tamanho dos pontos das armas de carregamento, aumentando Então vamos primeiro pegar a arma. Então nossa arma será uma arma do tipo dois. Igual ao sublinhado das armas de carregamento nessa posição de índice, e precisamos obter ou criar a Então, eu vou dizer que var display é uma exibição de arma, e vamos definir isso como igual a obter ou criar uma exibição em uma posição de índice de I. E então, em nossa tela, uma vez que tenhamos adquirido isso, direi que a arma exibida será igual à arma em si. E como a atualização faz parte do setter e desse script, ela será imediatamente atualizada automaticamente Agora, eu falei um pouco sobre efeitos colaterais e, se você fizer o setter dessa forma, não está necessariamente 100% claro que configurar a arma atualizará automaticamente a interface do usuário Mas como isso é tão essencial para a exibição da arma, acho que não há problema em dizer aqui: Oh, nós configuramos a arma. Claro, a arma mostrará a arma atual. Mas como a exibição da arma é literalmente o que ela faz, configurar a arma e sugerir isso atualizaria a arma que ela será exibida na interface do Eu não acho que seja muito problemático com isso como efeito colateral Mas é definitivamente discutível. Então, agora só precisamos obter ou criar a tela. Então, funcione, obtenha ou crie uma exibição com o parâmetro de índice, e isso será um número inteiro, e retornaremos uma exibição de arma Então, digamos que a exibição var do tipo de exibição de arma seja igual à exibição de pontos Get no índice. Ok, então isso pode ser nulo. Então, se display não for igual a null, nós apenas retornaremos o display Caso contrário, precisamos criar um aqui e adicioná-lo à tela para que a tela seja igual à instância da cena de exibição da arma E eu digitei esse nome errado. Então, aqui, Controle C, Controle V. E então queremos adicioná-lo como filho a essa interface de usuário, ou melhor , ele vai para o contêiner HBox. Então, espere. Preciso de uma referência ao contêiner. Portanto, exporte o contêiner de exibição V, e isso será qualquer tipo de contêiner. Só precisamos exportar isso na interface do usuário. Em seguida, pegaremos o contêiner de exibição e adicionaremos o display como resultado disso. Dizemos que as telas não se abrem por meio de uma nova tela. E então, por fim, queremos retornar a tela, girar a tela Portanto, ele deveria ser criado aqui , se ainda não existisse aqui. Então, isso resolverá a criação dos novos monitores. Agora, e se removermos uma arma? Depois de percorrermos as armas e configurarmos todas as telas, queremos verificar se a matriz de armas é realmente menor que a nossa matriz de telas e, em seguida, remover as telas extras. Então, digamos que removemos uma arma do jogo e queremos que nossa tela aqui seja atualizada. Bem, isso vai ser uma referência nula na tela agora Então, podemos dizer que, para exibição e exibição arma I display dot é nula, então podemos simplesmente liberar a tela Então, exiba o ponto Q gratuitamente e espere aqui. Eu preciso ter esse sublinhado lá porque é uma variável privada Portanto, temos nosso ponto de exibição Q livre. Portanto, temos nosso ponto de exibição Q livre e queremos redimensioná-lo para nosso SI de carregamento Então, vamos realmente entender isso como uma variável local do tamanho de nossas armas. Agora podemos reutilizar o tamanho das armas aqui e aqui embaixo também. Ok, então, para percorrer essa função novamente, ela atualiza e cria telas conforme necessário para mostrar todas as armas, remove todas as telas que tenham armas nulas e redimensiona a matriz de telas Então, obtemos o número de armas. Para cada uma dessas armas, atribuímos a arma à posição de exibição correspondente. Então, depois de fazermos isso, examinamos todas as telas mais uma vez e, tecnicamente, poderíamos ir do alcance da arma até o final dela, mas otimizá-la um pouco para não ganhar muito, porque estamos mostrando apenas seis itens aqui Mas se a arma exibida for nula, mas aqui se a arma exibida for nula, que poderia ser se removêssemos uma arma, então vamos deixar a fila na tela e redimensionar o conjunto de telas para que esse tamanho corresponda às Em nossa tela G ou create, se a exibição existir no mesmo índice, ela apenas retornará isso e nós o usaremos. Caso contrário, ele criará uma nova cópia da cena e, em seguida, a aplicaremos no contêiner HBox Ok, agora no inspetor, temos que atribuir aquele contêiner HBox Poderíamos renomeá-lo para Displays Container se isso ajudar Então exibe o contêiner, mantendo a nomenclatura consistente. E já temos a tela de armas aqui. Então, isso funcionará em Ok, então vamos executá-lo e ver se está funcionando em execução agora. Então, corremos e não conseguimos encontrar o carregamento de armas porque acho que pode ser chamado de carregamento de armas Então você pode ver que Fine Children é meio frágil assim Então, temos armas carregadas lá fora. Então, vamos tentar encontrar o carregamento de armas com o S e depois executá-lo Ok, então chegamos onde temos textura de ponto igual ao ícone de ponto de definição de ponto da arma Ok, então encontramos outro problema. Eu não configurei o texto etiqueta na tela da Então, vamos entrar na exibição de armas e corrigir isso. No canto superior direito, quando você estiver deslocando a arma, atribua a textura com um clique duplo e, em seguida, atribua Ok, e vamos executá-lo mais uma vez. Veja se isso resolve os problemas. Ok, então aqui, quando não há arma, isso vai causar um problema. Então, talvez nós realmente queiramos que ele coloque uma arma antes de atualizá-la Portanto, como a atualização ocorre aqui quando configuramos a arma, removerei a atualização pronta Não é realmente necessário e, na verdade, causa mais dor de cabeça aqui do que precisamos. Então eu vou clicar em play. E tudo bem, lá vamos nós. Spear one lá em cima, no canto superior esquerdo Vou até aqui e selecionaremos o novo item. Agora, isso não vai funcionar porque não configuramos sinais. Ok, então um erro que eu cometi, quando você chama o Git em um índice que não existe em uma matriz, ele vai te dar erros fora do limite Então, o que realmente devemos fazer é garantir que o índice esteja na matriz. Então, vamos dizer que se exibe , digamos que o tamanho é maior que o índice, então vamos retornar esse bit aqui, exibe pontos do Índice Git Claro. Em seguida, podemos remover a declaração variável var display weapon display aqui embaixo até quando instanciarmos a cena de exibição, e removeremos essa linha na parte superior 52. Ladrilho 51 Conectando sinais e configurando a interface do usuário de armas para exibição dinâmica: Ok, então temos mais alguns sinais para conectar em nossa visualização de armas e na tela de armas para que, quando estivermos no jogo, ela mostre corretamente a configuração correta das armas depois de atualizarmos a interface Então, uma questão muito importante aqui será quando nosso equipamento adicionar uma arma, chamando o método de adição de arma que vamos conectar ao sinal de mudança de arma, que acho que ainda nem criei Então, vamos entrar no carregamento de armas. Vou clicar com o botão direito aqui, abrir o símbolo. Agora estamos no script GD do ponto de carregamento de armas. Portanto, temos o método de adicionar armas e queremos admitir um sinal aqui para que nossa visão possa responder a isso. Então, no topo, vamos criar nossa mudança de armas de sinal. Se quisermos, podemos passar o conjunto de armas para o sinal. Então, armas, que é um conjunto de armas 2 D. E agora só precisamos admitir isso aqui embaixo quando chamamos adicionar arma. As armas são trocadas, os pontos de emissão são emitidos e nós entregamos as armas Está bem? Agora, de volta ao nosso script de visualização, assinamos so on ready Depois de obtermos o loadout, queremos fazer com que as armas de sublinhado mudem conexão E vamos dizer que nenhuma arma foi trocada. Vamos fazer esse método aqui embaixo. Então, a função das armas mudou. O parâmetro é a arma P, que é uma matriz de duas armas D, que retornaremos vazias Agora, vamos chamar a atualização aqui. Isso é tudo o que precisamos fazer porque a atualização já controla a carga das armas e quais armas temos, qual é o tamanho delas Então, na verdade, não vamos usar diretamente essas armas P aqui, então vou sublinhá-las para que não recebamos um aviso E agora, antes de clicarmos em play, quero ter certeza de que nossos itens estão realmente definidos corretamente. Então, no sistema de arquivos inferior direito, vou pesquisar o item. Temos o item Syth Então, vamos ver se vamos para o topo agora, este é um item sem nome, sem descrição, e também precisa de um ícone Além disso, parece que eu também entendi o item errado, parece que tenho a definição errada do item. Isso faz muito sentido agora, por que a arma da foice não apareceu Então, vamos carregar rapidamente aqui a definição de foice. Ok, então isso está configurado corretamente, mas temos que definir nosso nome de exibição. Foice. Então, para a descrição, vou colocar um projétil que gira ao redor da tela e pode atingir muitos inimigos Essa é basicamente sua principal diferença em relação à lança. E para o ícone, bem, vamos entrar na definição de foice Vou clicar com o botão direito do mouse no ícone aqui e copiá-lo , fechá-lo e colar no ícone aqui. Ok, agora precisamos fazer algo semelhante no item da lança. Então, clique duas vezes na lança. Em seguida, iremos para o canto superior direito. O nome de exibição será lança. Portanto, a descrição pode ser um projétil básico que avança da direção em que o personagem, eu acho, direi, está olhando E então o ícone, nós apenas copiamos isso da definição para o ícone do item. Assim mesmo. E isso basicamente deve lidar com muito disso. Então, vamos jogar. Acho que a única coisa agora é que não estamos conectados a um sinal de subida de nível, mas tudo bem, podemos ver a lança um no canto superior esquerdo Vamos pegar nossa foice. Então, a foice 1 está agora lá em cima, e nosso projétil de foice também está sendo lançado Podemos ver que está girando. Talvez sua velocidade de movimento não seja realmente suficiente porque queremos que ela realmente gire em um círculo ao redor do jogador. Mas vamos garantir que ele possa atingir. Sim. Ok, então parece estar atingindo inimigos Bem rápido, nas opções geradas, há um aviso sobre o sombreamento selecionado e o sinal já declarado Então isso não é ótimo. Vou pegar a matriz selecionada e gerar opções. Isso está no script de visualização de armas. Isso está no contêiner da caixa de recompensas aqui. Vou pegar isso e controlar R. Vou renomeá-lo para itens selecionados Vou clicar em substituir, não substituir tudo, porque lembre-se que não queremos mexer com os nomes dos sinais aqui Então, substitua somente dentro dessa função, e queremos ir até aqui. Também devo combinar maiúsculas e minúsculas e palavras inteiras para ajudar a reduzir o número de coisas extras selecionadas. Portanto, o datapen selecionado agora é o datapen de itens selecionados e, em seguida, retornamos OK. Então, isso deve lidar com esse aviso. Ok, então a cena do nosso site não estava girando exatamente da maneira que esperávamos Então, um problema com os scripts do projétil é que, se eu tentar dizer, execute essa cena sem lançá-la primeiro de uma arma de dois D, vamos preparar esse problema em que ele atingirá a afirmação Então, o que poderíamos fazer em vez disso para fins de teste, principalmente, é ter uma direção padrão. Então, vou dizer que a direção será igual ao vetor dois pontos à direita. Então, basta ter esse padrão lá. Removeremos a declaração. Por isso, também vou exportar o nível de variação para que tenhamos a opção de definir um nível de arma no inspetor Não deveria ser necessário para nós, porque na maioria das vezes, lançaremos por meio do método de lançamento, certo? Foi assim que montamos o projétil. Mas caso queiramos testá-lo no editor, eu poderia configurar um nível de teste aqui e o direito para que pudéssemos definir a velocidade padrão da arma. Então, vamos clicar em Play. Ok, agora com essa configuração, devo ser capaz de executar esse script e ver como ele se moverá por padrão, o que é muito útil para nós lá no topo. Eu poderia até criar uma cena de teste em que tivéssemos uma câmera olhando para o centro da uma câmera olhando para o centro da nossa, para nos ajudar ainda mais em nosso propósito de depuração visual, que não precisemos rodar o jogo completo e subíssemos de nível toda vez que quisermos testar o Então, vamos criar nossa cena de teste. Então, essa será uma nova cena em dois D, e eu a salvarei na raiz. Então, vamos chamá-lo de teste de armas dot TSCn. Guarde isso, e eu vou colocar a arma da foice. Então, foice, arma, ponto TSN. Acabamos de colocar isso na raiz. Vou renomear o nó raiz. Então teste as armas e, em seguida , clique com o botão direito do mouse e adicione uma câmera ao D. Então isso terá um zoom de três. Eu acho que é bom. E vamos tentar executar a cena clicando no botão reproduzir cena atual. Ok, então a razão pela qual não vemos nada aqui é porque não devemos colocar a arma de foice aqui Devemos colocar o projétil Syth. Então, meu erro. Então, vamos procurar por sythe dot Tscn e soltar isso na raiz. Agora, se aumentarmos o zoom, devemos ser capazes de ver isso. Ok, isso é bom. E vamos apertar o botão Executar a cena atual. Agora podemos ver como ficará quando nossa foice disparar para a direita, e isso tornará muito mais fácil e rápido depurar Agora, com nossa configuração de cena de teste, podemos ver como nossas armas giram e se movem na tela, mas não é exatamente isso que estamos procurando Então, o que realmente precisamos mudar aqui é voltar à cena da foice, esse nó rotador Se quisermos que a arma ou o sprite gire em torno de um ponto central, precisamos mover esse deslocamento do rotador para a direita, mantendo nosso sprite e a caixa de acerto na esse deslocamento do rotador para a direita, mantendo nosso sprite e a mantendo nosso sprite e Então, vou mover temporariamente esses dois para fora do rotador dois D para que eles não se movam com ele, e então vou mover o rotador dois D para a direita assim Ok, então isso nos dará um deslocamento para que tudo ao redor possa realmente girar em torno desse ponto em vez de apenas girar aqui em Então, vamos trazer isso direto da caixa de impacto de volta para o rotador dois D. Ok, bom. E talvez queiramos aumentar a velocidade X para 25 Vamos examinar a cena e ver se isso nos dá o que estamos procurando. Então, sim, mas isso é um pouco rápido demais, na verdade. Então, talvez nós apenas baixemos isso volta para o padrão de dez e o executemos novamente. Então, é a rotação que está realmente fazendo isso. Então, ou precisamos de uma rotação mais lenta ou talvez precisemos que ela esteja mais à direita Não tenho certeza de qual. Isso é uma espécie de adivinhação para mim aqui. Então, se acontecer de você mover o rotador com esse sprite e a caixa do quadril embaixo dele, certifique-se de movê-los de volta ao ponto central 00 E então vamos executar a cena de teste e ver. Acho que apenas 360 graus é muito rápido. Ok, então eu vou voltar para a terceira cena e vamos diminuir os graus de rotação. Vamos cortar isso pela metade, talvez 180. E então vamos executar nossa cena de teste. Ok, provavelmente é muito mais parecido com o que queremos, mas eu também aumentei muito a distância do rotador agora Ok, então vou mover o sprite dois D para fora e a caixa do quadril para fora, e vamos mover o rotador de volta bastante para dentro Mova o sprite e a caixa do quadril de volta para baixo do rotador. E vamos testá-lo na cena de armas de teste. Ok, então vamos executar isso. Uh, quase. Mas talvez a velocidade do projétil ainda seja muito rápida. Eu não sei Precisamos testá-lo no jogo. Então, vamos clicar em play, e isso realmente executará o jogo principal porque essa é a cena principal. Então, vamos pegar a lança, o projétil da foice. E essa é a aparência da nossa arma de foice no momento Não tenho certeza se estou muito feliz com o padrão, mas pelo menos está cumprindo o conceito geral. É principalmente uma questão de termos que ajustar as variáveis agora Deixe-me tentar fazer com que o jogador seja atingido e destruído. Ok, então ele ainda se retira da cena, mas teremos que criar a tela de game over. Como parte do aprimoramento do curso. Então, vou executar isso mais uma vez para pegar nosso projétil de foice É como ir para a direita. Eu prefiro que seja mais, tipo, centralizado para a direita Deixe-me ver se consigo ajustar isso. Talvez seja o resultado da velocidade X. Vou tentar desligar isso e vamos rodar a cena novamente. Ok, então agora é um pouco assim. Voltará ao início aqui. Porque o rotador não tem velocidade extra. E a direção em que ele é lançado depende se você está virado para a esquerda ou para a direita. Então, pelo menos, é uma aplicação igual para os dois lados. Talvez você goste disso. Talvez você não. É principalmente uma questão de ajustar as variáveis para obter o padrão desejado para o movimento Então, pelo menos por enquanto, eu diria que é bastante aceitável. Vamos aumentar o nível da arma de lança aqui. E isso vai aumentar o nível da arma, mas não temos um sinal de aumento de nível conectado aqui. Ok, então onde fazemos isso é na tela de armas. Vamos entrar na exibição de armas. Quando colocamos a arma aqui, precisamos conectar os sinais. Mas, nesse ponto, eu diria que isso é, na verdade, colocar muita coisa em um setter para a arma Isso meio que esconde o que deveria fazer. A atualização foi boa. Mas acho que se estamos conectando sinais e atualizando a interface do usuário, isso é demais. Então, vamos criar uma arma com conjunto de funções. que passará em uma arma, a arma 2 D. Ok, então se a arma não for igual a null e diremos que o nível de pontos da arma alterado está conectado, então faremos um retorno de chamada aqui, sublinhando o nível da arma Claro, isso vai nos dar um erro porque o nível alterado ainda não existe na arma. Então, vamos pular na arma, procurar o símbolo. Vamos criar um sinal aqui, nível do sinal alterado, que você passará no nível, que é um número inteiro Se isso é tudo que vou fazer com esse nível, e acho que é, então vamos dizer valor definido. Diremos que se o nível for igual ao valor, retornaremos com sabedoria, nível é igual ao valor e podemos alterar o nível Nos níveis. Então, estamos meio que tornando essa propriedade observável, e isso é tudo que vou mudar lá O motivo dessa proteção é que, se definirmos o nível como o nível, não queremos emitir sinais de interface de usuário desnecessários porque o nível, na verdade, não mudou Portanto, só precisamos fazer essa atualização se estivermos configurando-a com um novo valor. Agora, eu esqueci dois pontos aqui no topo, então isso eliminará esse erro Agora, em nossa exibição de armas, o nível foi alterado. Precisamos criar uma função de retorno de chamada alterada no nível da arma função de retorno de chamada alterada Então, a função copiar e colar no nível da arma mudou, e então temos o nível P, que é um número inteiro Vamos retornar void e queremos atualizar a interface do usuário Uh, mas o que estamos realmente fazendo aqui é nos desconectar do sinal da arma antiga, se ele existir Então, verificamos se a arma antiga existe aqui, verificando se ela não é nula Então, se o sinal estiver conectado, precisamos desconectá-lo. Nível de pontos da arma alterado ponto de desconexão no nível da arma alterado Sem parênteses. E essa parte é apenas verificar se o sinal está realmente conectado antes desconectarmos um sinal que não está Então, apenas guardas de segurança. Ok, então preparamos a arma antiga para ser totalmente desconectada, então podemos trocar a arma agora Então, vamos dizer que arma é igual à arma P, e então queremos nos conectar a esses sinais de mudança de nível de armas Mas também podemos colocar um guarda verificar se ele já está conectado por qualquer motivo. Isso é um pouco excessivamente seguro, mas poderíamos dizer que, se o ponto de mudança de nível da arma já estiver conectado a essa função aqui embaixo, e quisermos fazer o inverso Então, estamos dizendo que se não estiver conectado, precisamos conectá-lo. Então, o nível de pontos da arma mudou, dot Connect, sublinhado no nível da arma mudou E também queremos atualizar, com certeza. Então, vamos atualizar isso Então, quando configuramos a arma, nós atualizamos e, toda vez que o nível muda, nós atualizamos Então, agora queremos pegar essa propriedade e sublinhar e torná-la privada Então, isso será mais como uma variável privada. E não queremos modificar isso diretamente. Queremos encorajar fortemente qualquer pessoa que esse script a usar o método set weapon em vez disso. Então, vou selecionar aqui, e vamos controlar e basicamente encontrar e substituir. Portanto, certifique-se de combinar maiúsculas e minúsculas e palavras inteiras, e então vamos mudar isso para arma de sublinhado Acho que podemos nos safar com a substituição em massa aqui. Portanto, todas as 11 instâncias substituem todas. Esse é o Control R para abrir esse menu. Agora, é claro, se rodarmos o jogo , obteríamos um erro porque estamos tentando configurar a arma, não sublinhar a arma do ponto de vista das armas Então, se formos para a visualização de armas, agora em nossa atualização, queremos chamar a arma display dot set na arma dois D com a arma dois D e remover isso Então, todo o motivo para mover o código de configuração de arma reativa para esse método explícito de conjunto de armas é para que saibamos que há mais coisas acontecendo aqui do que simplesmente definir o valor da arma A propósito, livre-se dessa atualização. E podemos até remover isso, mas aqui, neste momento, é basicamente apenas uma variável regular. Mas não queremos esconder o fato de que ele está conectando e desconectando sinais e atualizando a interface do usuário Pode ser um pouco mais explícito. Então, todo esse código poderia facilmente estar sob o configurador de variáveis de arma, mas ter essa grande função de bloco escrita meio que deixa mais claro qual é a nossa intenção E eu sei que isso meio me contradiz quando antes eu pensava: Ok, você pode simplesmente montar armas e usar a atualização Mas como também estamos emitindo sinais, acho que há muita coisa acontecendo, e não queremos esconder isso de ninguém que esteja tentando configurar a tela. Queremos que eles saibam: Ok, existe grande função de arma. E isso é lidar com todas essas coisas extras. Ah, certo. Então, vamos seguir em frente e rodar o jogo, e eu vou subir o nível da lança até o nível dois Ah, ok, então você pode ver que havia outra referência à variável de armas , mas nós a tornamos privada. Então, queremos que alguém consiga pegar a arma em vez acessar a variável privada lá Deixe-me dar uma olhada nessa função e ver se ainda precisamos dela. Ok, então, como a visualização das armas está funcionando para liberar as telas antigas, precisamos que a arma de exibição de pontos seja substituída pela arma de exibição de pontos Git Então, vamos criar essa função na tela da arma. Então, funcione aqui, arma Git que retornará uma arma para D. Vamos apenas dizer que, se for arma sublinhada, retornaremos arma sublinhada, senão retornaremos nula Então, por que se preocupar em ter essa função de arma Git quando você pode simplesmente acessar diretamente a variável de arma Bem, tornamos essa arma privada porque queremos ter certeza de que encorajamos qualquer desenvolvedor a usar a função de configuração de arma explícita E como essa é uma variável privada, não devemos acessá-la de fora do script. Então, precisamos de uma função pública Get weapon para acessar isso. Então, é basicamente encapsular e impedir outras pessoas façam coisas com o script onde não deveriam fazer isso com o Agora, mais uma vez, o sublinhado é apenas uma prática de indicar que ele deve ser privado de forma eficaz, mas o GD Script realmente não tem privado ou público como palavras-chave Portanto, você não pode realmente impedir que alguém o acesse. Você só pode indicar sua intenção com o sublinhado. Ok, então vamos fechar isso e rodar a cena mais uma vez. Vou subir o nível da nossa lança. E vamos fazer o upgrade da lança. Então você pode ver que Spear foi para o nível dois ali mesmo e no canto superior esquerdo Claro, essa interface do usuário é muito pequena, preciso aumentá-la. Então, vamos para a jogabilidade UI Canvas, e eu vou clicar aqui. Na verdade, vou mudar o layout e centralizá-lo. Então, Anchors ficará no centro, e então eu quero compensá-lo a partir daí, mais ou menos Também entre na cena de exibição de armas. Então, se eu for transformar aqui, ficarei mais parecida com 400 pixels por 75. Quero ter certeza de que a âncora ainda está centralizada, para que eu possa personalizá-la aqui e depois voltar para a parte superior central para recentrá-la Vamos dar uma olhada na jogabilidade UI Canvas. Ok, isso ainda é bom. Vou entrar na exibição de armas a partir daqui novamente. E acho que o principal é que precisamos apenas garantir que cada uma dessas exibições individuais, o ícone esteja configurado para um tamanho mínimo. Então, se eu olhar a exibição de armas aqui, vamos pegar o tamanho mínimo e criá-lo. Poderíamos até dizer 96, 96. Vamos torná-lo grande e depois reduzi-lo, se necessário Então, o rótulo de texto aqui, eu também preciso que seja maior ? Talvez eu tenha. Vamos simplesmente substituir o tamanho da fonte aqui. E eu vou fazer com que seja, digamos, 16. Ok, isso é o que está acontecendo agora 32. Ok, então vamos tentar 32. Diminua o zoom. Vamos apertar o play. Como está na interface do usuário no momento? Ok, isso é muito melhor. Então eu vou pegar a outra arma. Nós temos nossa foice. Então lança, foice Acho que a única outra coisa é que talvez um pouco de contêiner de margem ajude. Então, feche o jogo e, na visualização de armas, nosso contêiner de margem, vamos substituir o tema Estou pensando em constantes de dois em todos os lados. Vamos clicar em play. Execute-o. E isso não ajudou muito. Vamos fazer quatro pixels em todos os lados, eu acho, e apertar play. Ok, isso é pelo menos mais visível. Vou fazer com que sejam seis. Então, seis de todos os lados, isso deve ser suficiente. Ok, então entramos no modo de jogo. Ok, agora temos uma pequena barreira entre nosso contêiner individual e a visão geral das armas. E isso parece muito mais sólido. Então, está mostrando o tipo de arma que temos e o nível da arma, e essa é provavelmente a maior parte do que realmente precisamos que ela mostre. Então, acho que estamos prontos para ir aqui. Deixe-me subir de nível para curtir. Vamos pegar o Syth Level 2. Sim, Syth também está subindo de nível corretamente. Então, isso basicamente ajuda a configurar a visualização das armas e a tela cheia, com todos os sinais conectados, corrigindo os itens, garantindo eles tenham uma descrição e um ícone, e apenas com aquela interface de usuário clara, qual podemos ver o que realmente está acontecendo com nosso jogador 53. Ladrilho 52 - Criando itens de aumento de estatísticas para atualizações de jogadores: Portanto, com nosso sistema de nivelamento trabalhando a capacidade de escolher um item de arma e atualizar nosso carregamento de armas com uma nova arma ou um nível aprimorado de uma arma, agora seria o momento perfeito para adicionar a habilidade de escolher uma atualização não relacionada a Por exemplo, um item de aumento de etapa, que aumentará permanentemente nosso HP ao subir de nível E podemos até mesmo transformá-lo em um item que tem uma chance rara de derrubar inimigos, se quisermos Em nossa pasta de itens, no canto inferior esquerdo, vou expandir isso e criar outro tipo de item. Vou clicar com o botão direito aqui e criar um novo script. E poderíamos chamar isso de item Stat Boost dotGD. Isso se estenderá a partir do recurso. Então, é uma espécie de tipo de definição. E então, em nosso item Stat Boost, vou abri-lo e dar a ele o nome de classe Stat Boost Ah, e isso na verdade vai se estender da classe básica do item, não do recurso. Então, se olharmos para o item, temos o Trapply e o Can apply Então, vamos pegá-los porque precisamos implementá-los em nosso Stat Boote Então, eu vou apenas colá-los aqui. Então, para se inscrever, queremos verificar se o alvo tem, , um bloco de estatísticas e B. Esse bloco de estatísticas tem a estatística que estamos tentando aumentar Poderíamos criar várias classes diferentes para, digamos, aumento de HP e item de redução de resfriamento. Mas, em vez disso, vamos simplificar isso com um nome estatístico de export var, que é um nome de string E vamos definir isso igual a nada por padrão. E então vamos fazer uma alteração no valor de export var, que é um float E vamos definir isso igual a 0,0. Então, primeiro de tudo, quero tirar o Spblock do player, se ele existir Então, eu vou dizer que var Stats é um controlador de estatísticas, e vamos tirar isso de ptarget dot get, e vamos obter esse nome de estatística como Então, isso pode acabar sendo nulo. Então, se as estatísticas forem nulas, retornaremos false aqui Outra coisa que queremos verificar é a mudança de valor realmente definida. Então, se a mudança de valor for igual a 0,0, vou enviar um aviso. Não é possível aumentar a estatística se a mudança de valor for definida como 0,0 ou na verdade, digamos que a porcentagem é um pouco mais flexível e, em seguida, a alteração percentual do valor E retornaremos falso aqui. Então, a razão para isso é que, se não configuramos o item, ele realmente não fará nada, então vamos pular a aplicação e colocar um aviso para vamos pular a aplicação e colocar um aviso saibamos que esse é um problema que precisamos corrigir apenas alterando a propriedade de alteração de valor para outra coisa Não há uma função pronta para verificar essas coisas, como seria com um nó, porque os recursos nunca estão prontos. Então, este parece ser um bom lugar para colocá-lo. Vamos verificar isso antes de nos inscrevermos. Caso contrário, acho que podemos voltar à verdade. Acho que esses são os dois principais constituintes que estamos observando Então, a outra coisa que eu queria ter certeza, na verdade, era essa parte. Então, estamos vendo se as estatísticas têm o nome da estatística, então eu realmente configurei isso incorretamente Queríamos dizer se o ptarget dot obtém estatísticas aqui. Então, primeiro, estamos obtendo o controlador de estatísticas e, em seguida, queremos verificar se stats dot G stat Name Não é igual a nulo. Se isso for igual a null , retornaremos false Então, primeiro, garantimos que ele tenha um bloco de estatísticas, depois garantimos que ele tenha a estatística e, em seguida, garantimos que realmente configuramos esse item corretamente para alterar o valor Ok, então, uma vez que passarmos tudo isso, poderemos aplicá-lo. Então, aqui embaixo, eu quero pegar o controlador de estatísticas mais uma vez, então eu estou apenas copiando e colando isso daqui para baixo Obtemos o controlador SATs e, em seguida, queremos obter o valor atual e adicionar a alteração a esse valor Portanto, nosso valor atual será igual a stats dot GET stat name e, em seguida, vamos pegar isso e incrementá-lo Então, digamos que nosso novo valor será igual ao valor atual mais a alteração do valor. E então definimos esse valor nos Sts. Então, stats dot define o nome da estatística para o novo valor, e eu adiciono um pequeno erro de digitação lá, então certifique-se de que esses nomes estejam E então queremos voltar à realidade. Portanto, também podemos verificar aqui, mais uma vez, apenas para ter certeza de que as estatísticas ainda foram realmente encontradas. Portanto, se as estatísticas forem nulas, retornaremos false. E talvez queiramos realmente um erro aqui porque devemos verificar se podemos aplicar logo antes de aplicá-lo. Portanto, as estatísticas do controlador de estatísticas de push e erro não foram encontradas na meta de porcentagem S, porcentagem P. Então, isso vai pegar o nó e substituí-lo lá. Tudo bem Sim, então, para estatísticas que recebem um nome, estamos basicamente mudando isso para flutuante por enquanto O novo valor é flutuante, e nós o colocamos de volta no valor estatístico Agora, algumas de nossas estatísticas, como HP, são números inteiros. Então, quando colocamos isso de volta no controlador de estatísticas, ele o reduzirá novamente para um número inteiro e perderá nosso valor flutuante Portanto, a ideia aqui é que, se você quiser aumentar um número inteiro, certifique-se de usar valores não decimais no item real de aumento de estatísticas Portanto, perde um pouco de clareza, pois estamos apenas agrupando números inteiros e flutuantes na mudança de valor, mas isso nos dá a flexibilidade de poder lidar com a grande maioria de nossas estatísticas por meio de uma classe, em vez de criar uma para mudança de HP, outra para aumento percentual de dano, Apenas muito menos scripts nos quais as coisas poderiam dar errado. Então, vamos criar nosso item HP Boost. E na pasta de itens, no canto inferior esquerdo, vou criar um novo recurso, que será um item de reforço do SAT. Então, isso vai para a mesma pasta. Vou chamá-lo de HP Boost, sublinhar os pontos do item e salvá-lo Agora, à direita, temos nosso item SAT Boost. Então, o SAT que queremos mudar será Max HP, e gostaríamos que aumentasse 50. Agora, eu vejo uma falha aqui, que é que, se aumentarmos o MX HP, ele também não aumentará o HP básico Então, temos que tomar uma decisão sobre como queremos lidar com isso. Uma maneira seria que, sempre que aumentássemos o HP MÁXIMO, ajustássemos o HP automaticamente em nosso script de controlador de pilha nessa quantidade Então essa é uma opção. Deixe-me verificar o controlador SC se isso faz algum sentido. Então, pesquise o ponto gD do controlador de pilha e o projeto, abra-o e veremos que temos o MAX HP. Assim, podemos ver a mudança fazendo o MAXHP menos o e podemos dizer aqui que, se a mudança for positiva, afetaremos o No entanto, acho que isso está realmente começando a aumentar esse setter, e pode ser que, na verdade queiramos alterar o HP máximo em alguns itens, mas não o HP básico Então, acho que uma maneira um pouco melhor de fazer isso seria em nosso item de aumento de estatísticas. Na verdade, temos um dicionário de estatísticas que queremos alterar e depois as examinamos Dessa forma, podemos fazer MaxHP e HP ao mesmo tempo. Poderíamos até ter um item que aumente, digamos, HP máximo, HP e ataque de uma só vez, e isso exigirá apenas um pouco de quatro ciclos Então, vamos mudar isso, vamos torná-lo um export var Stat changes E este será um dicionário de nomes de strings com os valores flutuantes Está bem? Então, vamos nos livrar disso agora, e isso nos dará alguns erros imediatos. Portanto, queremos garantir que cada um desses nomes de string exista no controlador de estatísticas Então, poderíamos dizer que quatro teclas nas estatísticas mudam as teclas de pontos. Vamos apenas verificar se a chave está realmente nesse controlador. Então, se a chave de estatísticas do Git for nula, ela não tem as estatísticas, não podemos modificá-la, isso é um problema E então podemos simplesmente fazer aqui embaixo. Para o valor nas estatísticas, os valores dos pontos são alterados. Em seguida, verificaremos se o valor é igual a zero e, seguida, teremos esse problema, então substitua-os por valor. Ok, então, tecnicamente, aqui, estamos fazendo dois loops, e isso está abaixo do Então, a melhor maneira de fazer isso seria simplesmente obter o valor da chave. Então, direi que o valor var é igual à tecla de ponto G de alterações de estatísticas e, em seguida, podemos verificar o valor sem os quatro loops extras Então, vou cortar isso e colar aqui, remover os quatro segundos loops. Isso deve torná-lo muito mais eficiente e fácil de ler porque agora estamos lidando apenas com isso 14. Ok, agora aqui na parte inferior, precisamos fazer algo semelhante para teclas de ponto que mudam as estatísticas Precisamos obter o valor de cada um deles. Então, vamos rever isso, para que faça parte do ciclo quatro. E diremos que stats dot Get key. Isso nos dará o valor atual. Tomamos o valor atual mais a mudança de valor. Isso nos dá um novo valor. Então, de onde obtemos a mudança de valor? Bem, precisamos dizer que a mudança do valor de var é igual à tecla Stat Changes dot Get. Ah, hein. E então temos o novo valor quando os somamos , conjunto de pontos de estatísticas. Sobre o novo valor, espere. O nome do conjunto não foi declarado no escopo porque o nome do conjunto é a chave. Então, queremos definir a chave com o novo valor no controlador de estatísticas. Ok. Agora, vamos pesquisar o item no projeto. Vou abrir o item HP Boost. Agora temos a capacidade de lidar com várias mudanças de estatísticas de uma só vez Então, vou fazer o MaxHP e serão 50. Quero fazer o MXHP antes do HP porque quero aumentar o MX HP antes de tentar aumentar o Portanto, o HP também será 50 aqui. Então, aumentamos o MX HP e, em seguida, o HP subirá 50 Se você estiver no FHP, deve estar no FHP pela segunda vez. E então vamos chamar o nome de exibição aqui, HP boost. A descrição aumentará o HP máximo em 50. E então, para o ícone, vamos criar uma nova textura de atlas. Vou expandir isso. Vamos fazer o upload rápido do nosso projeto e eu obterei a folha de sprites de 16 por 16 Então, vamos editar a região e escolher uma. Então, amplie, temos algo parecido com uma poção de saúde, algo que faça sentido para nós Há uma gota de sangue que pode ser viável. Ou aqui está um coração. Essa é outra boa opção. Ok, eu meio que gosto dessa farinha. Então, vamos pegar essa farinha vermelho-sangue carmesim, e vamos escolhê-la para que possa ser o ícone do nosso item E vamos testar isso adicionando-o como uma opção em nossa cena de aumento de nível de jogadores. Então, na cena de seleção de aumento de nível, vou clicar em nossa seleção LevelUp E temos nossas opções de itens aqui. Vou carregar rapidamente um novo item. Então, esse será nosso item de aumento de HP. Vamos dar uma chance de queda de um e clicar em Adicionar par de valores-chave. Ok, agora podemos clicar em play e entraremos aqui. Vou subir de nível e vamos selecionar nosso aumento de HP. Escolha isso e você verá que, de repente, temos 160 HP, e é assim que subimos de nível. Então, você pode ver daqui que seria muito fácil aumentar outras estatísticas, como dano de ataque, redução de resfriamento, o que mais? Velocidade de movimento, etc., para seu personagem, pois você precisa dar atualizações 54. P53 Como implementar captadores HP Boost e aprimorar a interface do usuário: Conclua nosso sistema de atualização criando uma coleta que nos permitirá pegar e aplicar imediatamente um desses itens, como nosso item HP Boost Então, vamos querer pesquisar as picapes em nosso projeto Então, temos nossos captadores de objetos. Vamos criar um captador HP Boost. Comece duplicando a cena D de coleta de XP. Então, vou clicar com o botão direito do mouse e duplicar isso e , em seguida, este será o captador HP Boost, sublinhado dois D, claro, e clique duas vezes nele Ok, então a primeira coisa que quero fazer aqui é mudar o sprite para que seja o mesmo do meu item Então, vou clicar em Animated Sprite TwoD. Vamos ver a animação aqui e criar um novo recurso de quadros Sprite para que possamos definir um ícone diferente Vou adicionar molduras de uma planilha de sprites. Vamos entrar na arte. Não é uma fanta vermelha, veja ícones de Raven, folha de sprite completa, 16 por 16, amplie Verifique se, à direita, você definiu o tamanho para 16 por 16 aqui para que ele possa dividir a folha de sprite adequadamente E sim, vamos encontrar aquela flor que eu estava usando. Então clique nele, adicione a moldura. E bum, aí está o nosso item. Eu posso ver o captador XP, mas na verdade é apenas um captador que imediatamente adiciona Então, esse script realmente ignora toda a necessidade de ter o item Então, o que estamos procurando é mais um item que coleta dois D. Então vamos renomear nosso nó base, item coleta D, e vamos clicar com o botão direito do mouse, desanexar o script, clicar com o botão direito do mouse em anexar um novo script, e isso será uma coleta de sublinhado de item, dois D, isso vai se estender da coleta até D. Nós criamos isso, damos o nome de classe item coleta dois D. Então isso vai aplicar um item que coleta dois D. Então, vamos renomear nosso nó base, item coleta D, e vamos clicar com o botão direito do mouse, desanexar o script, clicar com o botão direito do mouse em anexar um novo script, e isso será uma coleta de sublinhado de item, dois D, isso vai se estender da coleta até D. Nós criamos isso, damos o nome de classe item coleta dois D. Então isso vai aplicar o item coletado até o objeto que o pegou. Então, na interface do nível, aplicamos imediatamente o item ao nosso jogador. Aqui está um pouco diferente. Temos que pegar o item no mapa do jogo primeiro, como pegamos o EXB e depois ele aplicará o efeito do item diretamente ao jogador Se adicionarmos itens em um inventário, esse método de aplicação seria mais como adicionar um item à matriz de inventário e partir daí, mas nosso jogo não precisa de inventários, então estamos basicamente pulando Mas nosso jogo realmente não precisa inventários além do carregamento de armas, que funciona de forma um Então, nós realmente não precisamos entrar nisso para este projeto. Portanto, nosso item Pickup two D, é claro, queremos exportar um item do tipo item. Está bem? Então salve isso e, em seguida, podemos clicar aqui e vamos atribuir, se quisermos, podemos atribuir o item padrão. Mas talvez eu deixe isso em branco. Deixe-me dar uma olhada no script D básico de pickup two, clique com o botão direito nele Portanto, precisamos implementar a função take. Então, vamos copiar isso no item pick up two D. Vou colar isso Vamos implementá-lo em um segundo. Eu também vou fazer a função underscore ready, retorna void E vamos afirmar que o item não é nulo. Cada item retirado deve ter um item atribuído para retirada. Na verdade, acho que assert é um pouco forte demais aqui. Eu provavelmente escolheria mais, como push error. Assim, podemos ver o que está errado no console, mas isso não interromperá o fluxo do jogo porque, quando instanciamos a coleta do item, provavelmente ela será uma queda, e não queremos necessariamente que isso interrompa completamente o fluxo de nossos testes de jogo Então, acho que o erro push é um pouco mais apropriado aqui. Então, vamos remover o sublinhado do alvo P. Então, primeiro, vou dizer que ponto do item pode ser aplicado ao alvo P, depois vou aplicá-lo ao alvo P. Portanto, o item não tente se aplicar ao pTarget. E se isso acontecer, eu o removerei do local da cena. Agora, talvez fosse melhor se a função T também tivesse um booleano para retornar false Então, aqui, a natureza de mudar isso para um booleano significa que teria que voltar para a classe base e mudar isso E então, qualquer classe que também substitua a função T, teria que alterá-la Então, essa é uma das falhas de depender muito da herança para suas classes, em vez de usar uma abordagem de composição, como você vê no inspetor agora, a composição seria mais como se você tivesse vários pequenos scripts diferentes, cada um pequenos scripts diferentes com seu próprio propósito, em vez de ter um script básico estendendo vários Então, por exemplo, o jogador pode ter um personagem estendido e, em seguida, pode haver outra classe acima do jogador, como Spearman ou dragoon, que adiciona mais Mas se você tiver muitos scripts dependendo diretamente uns dos outros, uma pequena mudança, como apenas mudar isso para um booleano, pode significar que você precise atualizá-lo em vários lugares. Então, apenas algo em que pensar. Na verdade, não é tão problemático aqui. Ok, então o que vamos fazer com essa coleta de itens é colocá-la no mapa do jogo agora Então, HP Boost Pickup. Nós temos isso. Salvamos isso no projeto. Oh, realmente, o que eu acho que eu quero fazer disso é fazer disso uma cena base, então eu vou renomeá-la como item de coleta dois D. Agora vamos procurar captadores Então, vou clicar com o botão direito aqui e vou fazer uma nova cena herdada E então, nessa cena herdada, eu posso atribuir o item. Então, vou carregar rapidamente nosso item HP Boost e depois salvá-lo novamente na coleta de itens como coleta HP Boost Dois D. E então essa é a cena que colocamos no mundo do jogo. De certa forma, criar uma cena herdada como essa é muito semelhante a estender um script e colocar toda a base em seu novo objeto Mas em certas circunstâncias como essa, em que estamos apenas mudando o tipo de item que a configuração da cena tem: o captador de aumento de HP, com o item de aumento de HP, mas, por outro lado, sendo apenas um item normal , coleta dois D. Acho que em casos como esse, isso realmente faz muito sentido Então, queremos colocar nosso item no mundo do jogo agora. Vou pesquisar o World Dot TCN. Ok, vou ampliar aqui. Temos um jogador lá, então vou procurar o captador HP Boost e tentar arrastá-lo para o mundo do jogo Eu poderia simplesmente colocá-lo lá, mas vamos colocá-lo primeiro nos captadores para que ele tenha o pai W certo para movê-lo Vamos colocá-lo ali e talvez um segundo aqui só para ter certeza de que podemos fazer isso duas vezes. Vamos apertar o play e depois vamos pegar nossa picape. Então eu vou andar até aqui, e bum, nós temos 150 HP. Aqui podemos escolher se queremos lança ou foice. Interessante, não está oferecendo a opção para a terceira picape. Talvez eu precise ser adicionado. E então eu vou aqui e obtenho nosso próximo aumento de HP. Portanto, existe nosso item permanente de aumento de Sp, que funciona de forma um pouco diferente da nossa EXP, que apenas modifica diretamente Então, vamos verificar a seleção de subida de nível e vou me certificar de que o item ainda está lá. De alguma forma, tudo começou, então vou carregar rapidamente o valor de um do item HP Boost , adicionado. Então, agora vamos tocar em play mais uma vez. Só vou me certificar de que está funcionando novamente. Obtenha o aumento de HP ao subir de nível, selecione-o. O HP sobe, selecionamos aqui e aqui, então obtemos três aumentos de HP Isso está funcionando bem. A última coisa que quero ajustar, e essa é rápida, é que para nossas seleções de caixas de recompensa, elas não diminuem para o mesmo tamanho Quando um deles tem uma descrição mais longa. Então, eu quero entrar na cena de seleção de recompensas. Clique na raiz e deixe-me ver aqui. Uma delas precisa se expandir até o fim. Então, na verdade, a maneira mais rápida de depurar isso seria clicar em play E enquanto o jogo estiver rodando, vou até aqui e vamos testar, alterar o tamanho aqui. E então vou voltar e ver se está atualizado. Ok, então nossa área de aumento de HP, deixe-me verificar a raiz. Isso está configurado para preencher e expandir. Talvez seja a descrição que precisa ser feita e expandida. Então, podemos ver que a raiz aqui já expandiu e preencheu o conjunto. Então, vou verificar o contêiner de margem e ter certeza de que também é assim. Então, faremos o dimensionamento do contêiner do layout. Preencher. Ok, então outra coisa que eu poderia ver na visão remota para ver as notas que estão realmente em execução no jogo. E vamos expandir a camada mundial do Canvas até a interface do usuário. Temos o nível de seleção. Temos nosso contêiner de painel embaixo dele, o contêiner de margem, o contêiner de caixa V e o contêiner de caixa de recompensas e nossas três seleções Então, por que esses tamanhos são diferentes? Então, podemos ver, se olharmos aqui à direita , que os tamanhos do Y são todos iguais. Isso é o que esperaríamos ao analisar isso. Eles estão todos esticados até o fim. Então, vamos encontrar o nível em que eles não estão. O menor é o terceiro. Então, deixe-me expandir isso. Clique em Margin Container. Podemos ver o contêiner de margem. É o tamanho máximo de 20 pixels, então não é isso. Vamos até o contêiner VBox. O contêiner VBox é 214. Isso também é o que esperaríamos porque o contêiner de margem tem uma margem. Então eu acho que na verdade é essa caixa de descrição. Você pode clicar nos nós e realmente ver uma caixa quando ela estiver selecionada aqui. Isso é meio legal. Acho que isso pode realmente ser novo. Então, nós só queremos que a descrição empurre tudo para baixo. Ok, então sabemos o que estamos tentando expandir. Então, na visualização local agora aqui no canto superior esquerdo, vamos clicar na descrição. Ah, e lá vamos nós. Lá vamos nós. Então, aqui embaixo, no tamanho do contêiner, está programado para começar a encolher Eu quero que isso realmente seja preenchido e expandido. Agora, se eu voltar para o jogo, ele vai até o final. Ok, então você pode ver isso, certo? Esses três estão caindo. Também gostaria que os tamanhos dos ícones fossem iguais. Então, talvez precisemos definir um tamanho absoluto específico para os ícones. Acho que talvez o ícone da lança tenha sido configurado usando um maior, mas quero ter certeza de que todos tenham o tamanho certo Então, se clicarmos no ícone Rec aqui, vamos tentar alterar o tamanho do keep para ignorar o tamanho E acho que isso os torna iguais agora. Sim, tudo bem. Parece estar alinhado. Se você tiver outros problemas, esse seria um tipo de processo de depuração que você pode usar para corrigir sua interface de usuário enquanto realmente executa o jogo Portanto, é muito útil porque você pode realmente ver como ele será atualizado imediatamente . Você pode alterar seu controle dentro do Gado e da cena local, e ele será atualizado imediatamente na visão remota. Então, essa é, na verdade, uma das coisas mais legais sobre Gudo Ok, então com isso, acho que nossos captadores de sistema de atualização, tudo o que precisamos, nesse sentido está funcionando muito bem agora Então, essa é realmente a maior parte do curso até agora. Vamos fazer algumas coisas refinadas, como salvar e carregar um sistema de pontuação, como quantos inimigos matamos entre as sessões de jogo, tela de fim de jogo para ver quando realmente perdemos Então, podemos ir ao nosso menu principal e reiniciar o jogo, esse tipo de coisa. Mas a jogabilidade principal está praticamente lá agora. Então, esse será o fim deste vídeo e, em seguida, entraremos na fase de encerramento e polimento do curso 55. P54 Criando um captador de poção de saúde para soltas inimigas: Quero adicionar mais um vídeo sobre como fazer a coleta de itens do seu jogo no Então eu criei a picape para o item de aumento de HP, mas quero criar um item que seja derrubado pelos inimigos Isso será apenas uma poção de saúde simples. Então, vou pesquisar nosso item HP boost no projeto e duplicar o captador HP Boost Então, clique com o botão direito e desça para duplicar e vamos chamá-la de Poção da Saúde TCN de dois pontos D. Agora queremos abrir essa cena, Health Potion tod dot Então, nosso item aqui se chamará Health Potion two D, apenas para indicar que está no mundo do jogo Two D. Para o item HP Broca à direita, vamos clicar no menu suspenso e torná-lo exclusivo Então, estamos basicamente pegando a base e criando uma cópia exclusiva dela, e agora vou clicar com o botão direito do mouse aqui e salvá-la como uma poção de saúde Então, clique com o botão direito em Salvar como e, em seguida, coloque-o no projeto e nos itens, e eu farei a poção de saúde Sublinhe o item TRS. Vamos alterar as mudanças nas estatísticas para aumentar apenas o HP em 25 e remover o HP máximo desse Agora, para nosso nome de exibição, direi Poção de saúde E para a descrição, direi que restaura 25 HP, ponto final E então, para o ícone, vamos selecionar outro ícone da nossa região e encontrar uma poção de saúde Tenho certeza de que há alguns deles aqui. Então, sim, mais perto do topo, temos mais do que alguns. Realmente, faça sua escolha aqui. Eu vou escolher o de aparência típica. E vamos selecionar isso. E então também precisamos pegar o mesmo ícone para o Sprite two animado D. Então clique lá, vá para a animação, faça novos quadros de Sprite e selecione selecionar dos quadros Ícones de arte, folha de sprite completa de 16 por 16, ampliam o tamanho do conjunto superior para 16 por 16 Em seguida, controle o zoom do meio do mouse até a parte superior e pegue a mesma poção de saúde, que está aqui Só deve ser selecionado um. Clique em adicionar. Ok, e aí está nossa poção de saúde Então, isso já deve ser capaz de funcionar. Deixe-me jogá-lo no mundo do jogo como uma cópia. Então, temos nossa poção de saúde dois D. Vou colocá-la aqui por enquanto, e então podemos usar a poção de saúde Então, na verdade, a saúde básica começa em 50. Então, se eu for até aqui, você pode ver que 50 vai para 75 de 100. Então isso está funcionando. Ok, então precisamos entrar na cena do esqueleto e modificar nosso componente de gotas, mas na verdade nunca configuramos uma gota para o esqueleto. Então, vamos para Oc. Vou apenas selecioná-lo aqui e, no Controle C, copiá-lo para o esqueleto Em seguida, no canto superior direito, temos nossas definições de queda, que já farão com que a EXP caia com um peso de 1,0 Então, queremos adicionar a habilidade de, às vezes, soltar uma poção de HP em vez da EXP Vou adicionar um elemento e clicar em uma nova definição de descarte. Então, apenas para fins de teste, darei a ele cinco gotas de peso, que significa que 86% das vezes ele perderá uma poção de saúde, não uma EXP, só para que você possa vê-la E então vamos carregar rapidamente nossa poção de saúde 2 D. Ok, então, para que nossos colírios realmente funcionem, também precisamos adicioná-los como uma chamada em nossa animação de morte Então, vamos clicar no reprodutor de animação, ir até Death e fazer uma chamada sobre drops aqui. Então, no início, vamos adicionar um método de chamada nas quedas. E vamos clicar com o botão direito do mouse em inserir uma tecla para soltar uma vez. Isso é bom. outro erro que eu cometi na retirada do item Quando enviamos o erro para o item não é nulo. Na verdade, isso deve ser pressionado se for nulo, porque estamos tentando verificar se realmente nos lembramos de definir um item de exportação na retirada do item Essa foi uma simples reversão lógica. Ok, agora vamos clicar em Play e vamos tentar derrotar um esqueleto Vou apenas coletar alguns itens em XP aqui, pegue o site. E vamos esperar que um esqueleto apareça. Enquanto isso, podemos ver que os orbes ainda estão perdendo XP Sempre, essa é a única queda possível, e aí temos um esqueleto Então, se derrotarmos esse cara, cerca de 86% das vezes, ele deve soltar uma poção de saúde Então, esse tempo não aconteceu. Teremos que derrotar mais alguns. E vamos ver. Recebemos a poção de saúde para desovar Sim, lá vamos nós. Poção de saúde Então, na verdade, vimos que os dois podem desovar. Outra poção de saúde veio desse esqueleto, outra poção de saúde Então você pode ver que a ponderação definitivamente está funcionando na grande maioria das vezes em que estamos recebendo a poção de saúde em vez da Então, agora que sabemos que está funcionando, podemos simplesmente ir até o esqueleto Vamos até o Drops. Vamos pegar a definição de queda da poção e torná-la 0,1 Então isso significa que dez em cada 11 vezes a EXP vai cair, e uma em cada 11 vezes a poção de saúde vai cair, e é assim que a ponderação funciona Você soma todas as possibilidades mais seus pesos, e suas chances são o peso daquela específica dividido pelo peso total de todas elas juntas Ok, e é basicamente assim que você adiciona uma poção de saúde ao jogo Então você pode ver que, uma vez que temos nosso item de estatística, nossos captadores que nos fornecem um item de estatística, e podemos simplesmente aplicá-los ao jogador e definir como um nome de string a estatística que estamos afetando, fica muito fácil modificar muitas coisas diferentes em fica muito fácil modificar muitas coisas diferentes 56. Parte 55 Implementando o tremor da câmera para efeitos de ataque e morte do jogador: Agora estamos passando para a parte polida do curso, que encerrará as coisas adicionando algumas boas metades Vamos começar com um tremor de câmera ao apertar para que nosso jogador torne o jogo um pouco mais intenso. E também faremos coisas como adicionar uma tela de fim de jogo e a capacidade de monitorar a pontuação mais alta. Então, vamos começar com a vibração da câmera. Vamos para o mundo. E no mundo, temos uma câmera duas D aqui. Então, poderíamos simplesmente anexar um script diretamente na câmera dois D. Então eu vou clicar aqui, anexar um script e, digamos, sacudir câmera dois D. Sublinhado dois D, eu diria E vamos criar e colocar isso, eu suponho, na pasta UI. Então abra isso e crie. Vou dar a ela o nome de classe shake Camera two D. E vamos trabalhar na configuração disso. Então, primeiro, precisamos de uma referência ao nosso jogador, como muitos outros scripts, para que, quando o jogador sofrer dano, possamos acionar o efeito de tremor. Então, vamos exportar o contexto var do contexto do jogador. Então, assim como antes com outros elementos da interface do usuário, temos acesso às estatísticas por meio do contexto. E então vamos adicionar algumas variáveis para controlar nossa força de vibração. Então, primeiro, exporte var Max shake strength, que é um float, e eu vou defini-lo como 10.0 por padrão Também podemos ter uma duração de shake. Então, exporte var shake duration, que é uma flutuação, e definiremos isso como 0,3 segundos por padrão E então eu quero um conjunto separado de variáveis para quando o personagem morrer. Portanto, essa deve ser uma sacudida extra forte para causar o impacto de : Oh, você perdeu seu jogador, você perdeu o jogo. Então, vamos fazer Export Var death shake strength, e isso será um float up padrão para 20,0 E então temos em export Var a duração do death shake, que vou definir como uma flutuação de 0,6 segundos por padrão Então, quando nosso script começar, quero obter as estatísticas do jogador. Então, eu vou dizer que var underscore stats será um controlador de estatísticas aqui, e então precisamos da função underscore Então, vamos contextualizar as estatísticas de pontos do jogador, e vamos definir estatísticas de sublinhado iguais a essas Vamos afirmar que isso não é nulo. As estatísticas G não são iguais a nulas. É preciso ter uma referência às estatísticas do jogador para sacudir a câmera. Ok, então quando nossa câmera estiver tremendo por todo o lado, queremos lembrar sua posição original para que, quando terminarmos, possamos retornar a essa posição Vamos ter outra variável aqui. Este será um vetor dois D, sublinhado o deslocamento original, que será um vetor 20 Ok, lembre-se do sinal de igual aí. Então, estamos inferindo que é um vetor do vetor dois ponto zero, e isso também o torna um vetor 20 Ok, então nosso deslocamento original em pronto será igual ao nosso deslocamento atual Então esse é o deslocamento da câmera porque nosso script estende essa câmera diretamente E então precisamos nos conectar ao controlador de estatísticas HP alterou o sinal. Então, sublinhe as estatísticas Hp hanged dot Connect. E vamos conectar à qual vamos conectar isso em HP alterado. Então, vamos criar essa função aqui embaixo, sublinhado na HP foi alterado, e ela terá os dados estatísticos Então, dados P e esses são dados alterados por estatísticas. Desta vez, quando tivermos nossa função de retorno de chamada, vou usar os dados P diretamente, porque eles são muito úteis aqui para determinar se estamos fazendo um shake normal ou um death shake Então, se a mudança de HP no evento for maior ou igual a zero, só queremos voltar porque não estamos tremendo com a cura ou porque o HP não muda Então, agora queremos verificar se o valor do ponto u do evento é maior que Zarel Então, o personagem ainda está vivo, essencialmente? Então, se for esse o caso, usaremos os valores normais de vibração. Caso contrário, usaremos o valor do death shake. Portanto, a força do tremor do sublinhado será igual à nossa força máxima de vibração e, em seguida, o tempo do tremor do sublinhado será igual à nossa retenção Nossa duração de Shake. Ok, então precisamos dessas variáveis locais aqui em cima. Então var ressalta que a força de vibração é uma flutuação e Var ressalta que o tempo de vibração também é É claro que o padrão será zero. Ah, e quando eu coloquei o evento aqui, eu realmente quis dizer Pdta Então, pata dot change e pdata dot neu. Ok, então, caso contrário, há um outro caso aqui, que é que a saúde está abaixo zero ou igual ou abaixo de zero, devo dizer. Nesse caso, vamos definir a força do tremor para os valores de morte. Então, a força do tremor do sublinhado será igual à força do tremor da morte, e o tempo do tremor será igual à duração do tremor da morte Ok, agora, há outra coisa aqui, que é que, dependendo da saúde do nosso personagem, podemos querer aumentar ou diminuir a força. É por isso que eu tinha a força de vibração MX aqui. No momento, sempre será o máximo de 10,0 que eu configurei lá Então, acho que uma boa maneira de fazer isso seria verificar quanto dano você causou versus qual é o HP máximo do personagem Então, se um ataque afeta metade da saúde deles, você quer que seja um tremor de câmera bem forte. Mas se for apenas um dano ao longo do tempo, tipo: Ah, ele causa um dano segundo, isso é muito irrelevante Você pode simplesmente fazer uma pequena sacudida ou eliminar completamente a sacudida Então, var, a taxa de dano será igual ao valor absoluto F, do ponto do evento hg. Essa é a quantidade de saúde que acabamos de mudar, e ela será dividida pelo máximo de um ponto, oh. Então, durante a edição, notei que a matemática aqui está incorreta. Chamar o máximo entre um ponto oh e o ponto estatístico MX HP não faz muito sentido aqui porque na verdade, queremos que a proporção esteja entre a mudança e a saúde, o valor absoluto disso, de qualquer forma. E o MX HP Então, na verdade, o que queremos fazer é dizer uma variação percentual. E o que realmente queremos dizer é o valor absoluto flutuante da mudança de ponto de dados p dividido pelo ponto estatístico de sublinhado MX Então isso nos dá nossa proporção, que deve ser de 0 a 100 Mas queremos acabar com isso. Então, digamos que a proporção fixa agora. Vou cortar isso e, digamos fixar F na variação percentual, e vamos forçá-la entre 0,0 e 1,0 Então, se por algum motivo nosso valor de alteração fosse realmente maior do que nosso MX HP total, digamos que sofremos 9.000 de dano e nosso HP máximo fosse 100 , isso seria na verdade uma mudança percentual de Então, na verdade, queremos limitar isso a 100% ou, se estivermos indo na outra direção, não pode estar abaixo de 0% de alteração. Portanto, nosso valor total será de 0 a 100, não importa quão grande ou pequena tenha sido a mudança Multiplique a força máxima de agitação pela proporção fixada. A última coisa que precisamos fazer aqui para garantir que isso não retorne como zero é pegar o MX HP e lançá-lo em um flutuador Então, isso é importante porque, caso contrário, inteiro dividido por um inteiro simplesmente diminuiria o ponto decimal antes mesmo de convertê-lo em uma Agora podemos correr e garantir que ainda esteja funcionando conforme o esperado, então vou encontrar um cara para nos atacar. Ok, e ainda temos aquele tremor de tela, certo? Claro, o da morte será muito maior. Então, como mudamos a matemática, talvez você também queira ajustar a força máxima de vibração e torná-la mais forte, como 20 ou 30. E lembre-se, isso sempre será uma porcentagem da força máxima de agitação. Então, você precisa levar isso em consideração quando estiver realmente descobrindo o quão forte será o tremor Então, vamos ver, aos 30, força máxima é mais ou menos assim. Talvez um pouco forte. Então, eu poderia até reduzir isso para 20. Como mais um número final. Ok, agora, finalmente, nós realmente precisamos do processo para o shake. Então, vamos até o topo aqui. Depois que o sublinhado estiver pronto, direi processo de sublinhado da função Então, estou apenas preenchendo isso automaticamente. E então vamos dizer que, se o tempo de agitação for maior que 0,0, então vamos realmente sacudir a tela. Então, como fazemos isso é com um pouco de matemática. Então, vamos dizer que o tempo de underscore shake underscore é menos igual ao Delta Então, removemos o tempo do tempo que estamos passando aqui, e então eu vou pegar o valor da vibração X e da vibração Y e aplicar esse deslocamento Portanto, var shake X será igual à faixa F aleatória de menos 1,0 a 1,0 vezes a força de agitação. Então, essencialmente, estamos obtendo uma direção aleatória multiplicada pela nossa força de vibração atual E então var shake Y, é claro, você pode imaginar que é o mesmo. Será igual ao intervalo aleatório de sublinhado F, 1,0 a 1,0 vezes sublinha a força de agitação Pegamos os dois e os aplicamos ao deslocamento da câmera Então, o deslocamento será igual ao deslocamento normal mais o vetor dois, e isso será agitação X e agitação Y. Então, basicamente, em cada atualização de quadro, a câmera vai tremer para uma nova posição aleatória ligeiramente diferente do deslocamento original, e fará isso até que o tempo de vibração Portanto, se o tempo de vibração for zero ou menor, digamos outra coisa, queremos retornar o deslocamento da câmera ao original Portanto, o deslocamento será igual ao deslocamento original. Ok, e se eu entendi direito, esse é basicamente o nosso roteiro. A última coisa que precisaremos fazer é atribuir o contexto do jogador e o inspetor Então, rapidamente aqui, menu suspenso, carregamento rápido, contexto do player. E vamos rodar o jogo e deixar nosso jogador ser atingido e ver se funciona conforme o esperado. Ok, então aqui está um orc, e nossa câmera treme toda vez que somos atingidos E aí está nossa câmera tremer on death, que é muito mais forte, como você pode ver. Então, essencialmente, esse é todo o nosso efeito de vibração da câmera. Obviamente, seria um bom momento para inserir a tela do GameOver para que possamos retornar ao menu Iniciar do jogo, que também precisamos criar 57. Ladrilho 56 Criando uma tela de jogo com a navegação do menu principal: Uma das últimas coisas que precisamos adicionar é uma tela de GameOver e uma tela de menu mínimo Então, o GameOver, é claro, vai aparecer quando nosso personagem for derrotado Portanto, precisaremos acessar o contexto do jogador novamente para que possamos verificar se I live é falso. Então, primeiro, vou abrir o sistema de arquivos e acessar a interface do usuário, e encontraremos nossa interface de usuário principal, o Canvas que facilitará um pouco o trabalho , para que possamos ver onde vamos colocar o jogo na tela. Então, por enquanto, acho que vou pegar a seleção de subir de nível e esconder isso. Isso facilitará o trabalho. E vamos usar a interface do usuário. Vou clicar com o botão direito do mouse em Adicionar um nó secundário. Então, queremos um novo controle esse controle será centralizado Então, no layout, vamos fazer âncoras de posição do layout e centralizar Agora, clique também para ir para o mouse e gire o filtro para Ignorar. E vamos clicar com o botão direito do mouse e adicionar um contêiner de painel a esse nó de controle. Então, recipiente de painel. Esse será o pano de fundo. Vamos pegar o recipiente do painel e esticá-lo. Então, aumente o zoom, certifique-se de que o contêiner do painel esteja selecionado aqui e vamos expandi-lo. Portanto, queremos que nosso contêiner de painéis esteja centrado em nosso controle principal Então, vamos ao layout agora e fazer o centro das âncoras do layout. Isso deve colocar as âncoras dos pais aqui no centro, então isso é bom Isso o tornará centralizado na tela. Vamos renomear o nó principal para a tela do GameOver. Além disso, clique com o botão direito do mouse e salve-o como uma ramificação na pasta UI, na tela GameOver Então, agora podemos simplesmente entrar nisso e editar isso puramente. Então, em nossa tela do GameOver, é claro que precisaremos de algo como um rótulo de rich text como título Vamos clicar com o botão direito do mouse em Adicionar um rótulo de rich text. E eu posso simplesmente dizer GameOver dentro de você. Provavelmente também queremos tornar o tema baseado em raízes como nosso tema principal do jogo. Então, carregue rapidamente o tema aqui, tema do jogo que nos dará a fonte de arte Pix Agora também podemos usar o rótulo Rich text e, digamos, conteúdo adequado. Também queremos dizer texto centralizado, também parece ser muito grande Acho que isso não será um problema, depois de adicionarmos o contêiner VBox, clique com o botão direito do mouse no contêiner do painel e adicione um contêiner VBox Mova o rótulo de rich text abaixo dele. Ok, isso corrige o tamanho já que agora é controlado pelo contêiner Vamos clicar com o botão direito do mouse no VBox e adicionar talvez um rato de textura e, em seguida, obteremos um ícone triste E então teremos um ícone do GameOver. Se usarmos textura e fizermos textura de atlas, nós a expandimos. E então, para o atlas, vamos carregar rapidamente nossos ícones Poderíamos usar o 64 64 aqui se quisermos manter isso no projeto. Editar região. Ok, e então precisamos diminuir o zoom e selecionar algo que seria bom para, tipo, um fim de jogo. Portanto, há muitas opções para escolher. Acho que esse crânio parece estar dormindo Não é muito escuro, não é muito fofo, então acho que pode funcionar. Deixe-me tirar isso do caminho para que eu possa ver o editor da região. Talvez eu precise realmente alterar o tamanho aqui. Vou tentar um passo de quatro no X e quatro no Y. Dessa forma, posso esticar isso para a direita, e então a esquerda e a direita se combinarão Também vou puxar um pouco a parte inferior para cima. Ok, então com a etapa 44, funcionou um pouco bem, então eu posso chegar mais perto aqui. Ampliamos nossa tela do GameOver. Acho que vou querer um clipe de filtro. Acho que também para o modo de alongamento, precisamos manter o aspecto centrado, e isso parece bom para mim Então, também adicionaremos uma caixa de descrição. Então, clique com o botão direito do mouse no VBox, adicione outro rótulo de rich text e podemos dizer que você foi derrotado Tentamos tentar novamente. Claro, vamos continuar com isso, conteúdo adequado. Sim. E então só precisamos de um botão aqui na parte inferior para ir ao menu principal. Então, clique em VBox, adicione um botão de nó filho Este botão exibirá menu principal. Vou anexar um script a ele. Então, esse será um novo botão. Ok, a seguir, vamos pegar esse botão aqui e eu vou renomeá-lo botão de mudança de cena porque vamos voltar ao menu principal Vamos anexar um script a ele. Então, este será o ponto GD do botão de mudança de cena. Crie isso. E queremos adicionar Export var ao mesmo caminho. Então, podemos realmente transformar isso em um arquivo de exportação, e isso seria aspas star dot TSCN Ok, então nosso caminho de cena é uma string e, quando estiver pronto, nos conectaremos ao sinal pressionado, então pressionar o ponto de conexão no botão pressionado e, em seguida, o sublinhado da função no botão pressionado simplesmente mudará Então, vamos fazer a mudança de ponto do Gtree de cena para arquivo, e colocamos o caminho da cena, e então isso mudará nossa cena atual para a cena do menu principal Como uma verificação importante, provavelmente ajudaria se disséssemos que o caminho da cena está vazio É igual a false e diz que deve haver um caminho de visão para o qual mudar quando esse botão é pressionado OK. Então, mais uma coisa que eu provavelmente quero é um contêiner de margem. Vamos clicar com o botão direito na tela do GameOver e adicionar um contêiner de margem Vou colocá-lo diretamente sob contêiner do painel e, em seguida, o VBox embaixo Está bem? Agora podemos definir valores no contêiner de margem e nas substituições do tema, algo como quatro para todos os lados, e isso fará com que pareça um pouco melhor, fornecendo um pouco de espaço para o texto. E em nossa tela de fim de jogo, precisamos ter certeza de que isso abrirá a interface do usuário quando o jogo for perdido. Então, vou anexar um novo script aqui. Interface de jogo na tela. Crie isso. Talvez queira um nome de classe aqui, game over screen. E vamos obter uma referência ao jogador por meio do contexto. Portanto, em Exportar vara, o contexto é do tipo player context. Diremos que a função underscore está pronta e, quando estiver pronta, contextualizaremos as estatísticas de pontos do player e obteremos a alteração Alive. Vamos nos conectar a isso e dizer que o jogador Alive mudou. Portanto, alteramos nossa função de sublinhado no player Alive. Não me lembro se isso tinha algum parâmetro, então clicarei no símbolo Alive changed e verificaremos se ele tem o Boole ativo, então volte ao script do game over, e precisamos disso como parâmetro aqui Então P Alive é um booleano. Isso retornará vazio. E se P Live for igual a false, mostraremos todo o menu do jogo aqui. Ok, agora, nosso estilo de botão de mudança de cena não vai funcionar porque não temos uma cena no menu principal. Então, vamos criar um espaço reservado. Adicione uma nova interface de usuário de cena e esse será o menu principal. Vou salvá-lo no projeto. Então, vamos fazer isso na raiz do menu principal do projeto e salvá-lo. E então, na tela de fim de jogo, vamos atribuir esse menu principal como um caminho para o caminho da cena e o botão de mudança de cena como este. Você pode simplesmente arrastar e soltar. Essa é a maneira mais fácil de fazer isso. Ok, também, antes que eu esqueça, vá para a tela Game Over e atribua o contexto do jogador. Então, basta carregar rapidamente esse recurso de contexto do player. Agora queremos ir para o mundo. Podemos ver que a interface do game over está aí. Então, vamos ver se podemos testá-lo bem rápido. E certifique-se de que podemos acessar o menu principal por meio dele. Então eu cliquei em Play. E está aí mesmo. Vou acessar o menu principal, e isso nos dá uma tela em branco porque, na verdade, não adicionamos nada a essa cena. É apenas um elemento de interface de usuário em branco, essencialmente. Então, isso está realmente funcionando. Acho que a outra coisa que queremos fazer é estar pronto para o game over na tela. Vamos apenas garantir que ele se esconda. Então, diremos que se esconda está pronto. Em nosso UI Canvas de jogabilidade, talvez também queiramos escondê-lo lá, mas não precisamos necessariamente dizer se isso ajuda. Mas vou deixá-lo visível por padrão para que possamos testar a altura. Então está escondido, e agora só precisamos ser derrotados, e ele deve aparecer se estiver funcionando corretamente. Então, dois acertos, três acertos, quatro acertos, cinco acertos. Aí está nosso pop-up do game over, no menu principal, e o fluxo está funcionando. A última coisa que eu acho que preciso aqui é apenas redimensionar isso. Então, vou colocar a tela de game over dentro do nosso jogo UI Canvas, e vamos pegar a forma do layout e elevar a escala para três. Isso deve ser grande o suficiente. Para que eu possa testá-lo mais uma vez rapidamente no jogo. Ok, então um golpe, dois acertos, três, quatro, cinco acertos, fim de jogo. E temos o botão do menu principal. E esse é o fluxo básico. 58. Ladrilho 57 Rastreamento de alta pontuação e exibição de UI para derrotas de inimigos e tempo de sobrevivência: Uma coisa boa que falta em nosso jogo é uma pontuação alta, poder rastrear quantos inimigos derrotamos em um jogo e depois lembrar essa pontuação em um arquivo seguro para obter uma folha de pontuação máxima que podemos ver na tela do menu principal Então, para implementar isso, precisamos primeiro começar contando quantos inimigos derrotamos sempre que um inimigo é derrotado. Então, precisaremos de uma combinação de reportar o estado de morte a um gerenciador de estatísticas ou de alta pontuação e, em seguida, pegar esse valor após o término do jogo e salvá-lo para atualizar o arquivo Safe. Então, no início do curso, adicionamos um gerenciador de jogo Singleton e nunca fizemos muita coisa com Na verdade, a forma como implementei o game over screen acabou sendo apenas usando o contexto do jogador, em vez de ter que reportar diretamente ao gerente do jogo. Então, vamos realmente dar ao gerente de jogo um propósito para que possamos usá-lo no curso. Então, teremos um objeto dentro de um gerenciador de jogo para as estatísticas e depois o rastrearemos durante o jogo. E então definimos isso sempre que começamos um novo. Então, nos sistemas, vou clicar com o botão direito do mouse e fazer um novo script. Digamos que sejam estatísticas do jogo, que serão contadas por árbitros porque na verdade, vamos torná-las filhas do gerente de jogo Singleton Então, abra as estatísticas do jogo e, em seguida, digamos que, se nossos inimigos forem derrotados, o que será um número inteiro padronizado como zero, precisaremos de um nome de classe aqui no topo Então, estatísticas do jogo. E então, no gerenciador de jogos, terei uma função start, que retornará nula, que pegará nossas estatísticas de jogo e as redefinirá ou configurará para um novo objeto Então, para estatísticas de estatísticas do jogo. Serão estatísticas iguais às do GameStats dot nu. Vamos continuar com isso por enquanto. E quando o mundo estiver cheio, vou querer pegar as estatísticas do jogo e redefini-las. Então, vamos anexar um script ao mundo. Tudo bem, clique aqui, anexe um script. Vamos colocá-lo na cena base. Então crie isso e eu direi que a função está pronta, e diremos gerenciador de jogos dot SAT. Ok, então tudo o que precisarmos que nosso jogo carregue no início, teremos isso lá. Então, enquanto estivermos usando o script mundial aqui , seremos capazes de gerenciar isso. Talvez também queiramos dar a isso um nome de classe. Poderia acabar sendo um roteiro bem importante se continuássemos com a série. Então eu acho que merece o nome de classe mundial. Então, agora, sempre que começarmos um novo jogo, ele basicamente redefinirá as estatísticas. E então talvez denuncie o fim do jogo. Poderíamos considerar entrar aqui um pouco mais tarde e salvar as estatísticas de pontuação mais alta. Ok, agora eu quero modificar nossas estatísticas e quero relatar sempre que nossas estatísticas forem modificadas. Então, nas estatísticas do jogo, criaremos um sinal para nossos inimigos derrotados. Então, sinalize que os inimigos foram derrotados, alterados. Usaremos um valor e um número inteiro como parâmetro e seguiremos um padrão semelhante, e seguiremos um padrão semelhante sempre que atualizarmos o valor, evitaremos se forem os mesmos valores Se os inimigos derrotados tiverem o mesmo valor, nós simplesmente retornaremos. Caso contrário, estamos definindo um novo valor. Então, inimigos derrotados são iguais a valor, e então dizemos que inimigos derrotados trocaram o ponto m por um novo Ok, então sempre que atualizamos a propriedade, nós a reportamos com um sinal para que possamos observar a propriedade. E acho que isso é tudo o que precisamos para configurar uma interface de usuário. Ok, agora que isso está aí, sempre que tivermos o estado da Morte ligado, digamos, nosso orc ou ao nosso esqueleto, vamos entrar no script do estado da morte Então, em nosso estado de morte, acho que Enter faz mais sentido dizer estatísticas de pontos do gerente de jogo, EMS derrotado mais é igual a um, e é assim que atualizaremos esse contador acompanhando todos os inimigos que derrotamos Agora, a última coisa que precisamos é uma pequena interface de usuário para mostrar quantos inimigos derrotamos Portanto, dentro de nossa tela de interface de usuário de jogabilidade, vamos adicionar outra, vamos transformá-la em um contêiner de painel. Adicione o contêiner do painel secundário aqui e colocaremos o layout como âncoras no canto superior direito Vou esticar um pouco assim. Compense isso. Deixe-me chamar isso de visualização de estatísticas do jogo. Em seguida, clique com o botão direito do mouse em salvar uma ramificação como cena e a interface do usuário , é claro , entre na cena, e vamos clicar com o botão direito do mouse nela e criar um script. Então, essa será a visão de Gamestts. Posso dar a ela o nome da classe, a visão dos jogadores. E na visualização em dois D em que a editamos, vamos adicionar um rótulo para nossos inimigos reais derrotados. Então, clique com o botão direito do mouse em Adicionar nó filho. Começaremos com um contêiner HBox, eu acho, e depois clicaremos com o botão direito do mouse em Achil Node, rótulo Rich Text Vou apenas duplicar isso. Então, o primeiro será para mostrar o texto e, em seguida, o segundo será o número. Então esse será o rótulo estatístico. E então a parte inferior será a etiqueta do valor. OK. Portanto, o rótulo do SAT mostrará consistentemente inimigos derrotados, dois pontos, vamos nos adequar ao conteúdo E então, na segunda, colocarei colchetes, zero. Então, isso é apenas um espaço reservado. E acho que precisamos que eles se estendam para que possamos realmente vê-los. Então, vamos tentar fazer o layout, dimensionamento do contêiner e expandir na horizontal Sim. E então etiqueta de quantidade, mesma coisa. Vá para o layout. Dimensionamento do contêiner, expanda na, expanda na horizontal Ok, então agora isso é mais ou menos o que temos agora. Ok, agora pegue as estatísticas do jogo pressione Q para entrar no modo de seleção, e vamos reduzi-las ao que precisamos Um contêiner de margem também seria bom aqui, então vou clicar com o botão direito do mouse e adicionar um contêiner de margem secundária, e vamos colocar o contêiner HBox embaixo dele no contêiner de margem O tema substitui constantes e talvez quatro pixels em cada lado. Isso parece muito melhor. Acho que isso pode ser funcional o suficiente por enquanto. Vou voltar ao jogo UI Canvas e me certificar de que ele esteja novamente no canto superior direito como uma âncora, no canto superior direito, e depois o desloco pressionando W para movê-lo Em seguida, basta movê-lo um pouco para fora da esquina. OK. E então eu preciso, no script da visualização do GamestTS, eu preciso realmente me conectar ao sinal nos Então, a função já está sublinhada. Vamos fazer o gerenciador de jogos: estatísticas de pontos, inimigos derrotados alterados, conecte-se a inimigos derrotados alterados. Vou pegar esse nome e criar uma nova função aqui embaixo, função no inimigo derrotado foi alterada, que considerará a quantidade P e o valor inteiro retornado nulo, e vamos atualizar o valor Ok, então, basicamente, pegamos o novo valor e o colocamos no rótulo. Então, na Export VR. De qualquer forma, pegamos o rótulo de nossos inimigos derrotados e definimos o texto igual a uma sequência da quantidade e pronto. Só precisamos de dois pontos aqui no final. Talvez, quando estiver pronto, queiramos afirmar que existe o rótulo de derrotado do inimigo É necessário definir o rótulo de inimigos derrotados para mostrar a contagem ou a montaria de inimigos derrotados. Seremos um pouco mais precisos. Agora, clique na Visualização de estatísticas do jogo e entre na cena. E dentro daqui, queremos atribuir esse rótulo de valor. Então clique em atribuir e escolha a etiqueta do valor. E se eu estiver certo, isso deve ser tudo aqui. Então, vamos jogar e tentar. Tudo o que precisamos fazer é derrotar alguns inimigos e vê-los aparecer no canto superior direito. Então, o problema aqui é que as estatísticas não são iniciadas em nada, então eu quero clicar com o botão direito do mouse no símbolo Lou Acho que o problema aqui é que as estatísticas podem não ser definidas antes de serem executadas na interface do usuário, já que esse é o topo do mundo, acho que as crianças estão prontas primeiro Então, a melhor maneira de fazer isso, eu acho, seria dizer que as estatísticas são iguais a gamestts dot u. Então, isso sempre será criado quando o jogo começar E então queremos chamar stats dot reset. Então, vamos criar uma nova função para isso. Isso também significa que não precisamos reconectar os sinais porque ainda estamos usando o mesmo objeto Então, na verdade, é uma maneira melhor de fazer. Vamos entrar nas estatísticas do jogo e criar nossa função de reinicialização. Então, reinicie a função. Nós apenas devolvemos tudo aos valores padrão. Então, inimigos derrotados são iguais a zero, e isso deve ser tudo o que precisamos agora Portanto, agora as estatísticas devem ser definidas assim que o jogo começar, antes mesmo de o mundo ser carregado. E então, a partir daí, devemos ser capazes de nos conectar ao sinal. Ok, vamos tentar mais uma vez. Tudo bem, jogue. Ok, temos uma contagem no canto superior direito. Claro, é muito pequeno, mas podemos pelo menos ver isso. Então, vamos derrotar um orc e garantir que esteja funcionando. E temos um lá para aparecer se matarmos outro cara. Está bem? Aí temos três. Então, sim, a contagem está funcionando com certeza. Eu só preciso ampliar a interface do usuário. Então, na jogabilidade Canvas, vamos fazer isso aqui. Uma escala de transformação simples de três. Mova isso para a direita aqui. E agora precisamos realmente cortar muito desse espaço extra. Isso está ocupando demais sem motivo. Então, vou precisar de uma pequena edição lá. Vamos entrar na visão dos jogadores. Na verdade, vou alterá-la de volta para zero sem os colchetes que, antes de derrotarmos o primeiro inimigo, ela não tenha nenhuma exibição instável Ok, agora que o tamanho é muito grande, acho que muito disso é só definir manualmente o tamanho de visualização dos jogadores Então, vamos reduzir isso aqui para o que realmente precisamos. Então, podemos torná-los muito menores. E essa segunda visão não precisa ser tão grande quanto a primeira. Portanto, não há razão para que eles ocupem a mesma quantidade de espaço. Acho que o que realmente queremos é mais um contêiner de fluxo. Deixe-me mudar o tipo de contêiner de caixa H para um contêiner de fluxo H. Ok, agora vou até o rótulo do valor e vamos desmarcar expandir aqui E então vamos tentar pegar o tamanho mínimo personalizado e configurá-lo para, tipo, 40 pixels, provavelmente grande o suficiente, para que eu possa segurar pelo menos mil dígitos E então o resto do espaço será ocupado pelo inimigo derrotado. Também vamos mudar a visualização na base para o nosso tema padrão do jogo Quick Load. Sim, ok, isso também vai ter um grande impacto. Então, agora, se olharmos para isso, eu posso realmente reduzir isso. Eu deveria ter feito isso no começo, na verdade. Então, algo assim, esse é o nosso espaço para a etiqueta e o número ali. Podemos acessar o jogo UI Canvas e reduzir isso drasticamente Você pode ver que tudo o que não é aquele pixel do lado direito é consumido pelo rótulo de texto à esquerda. Portanto, é melhor que esses dois elementos não estejam tentando ocupar uma parte igual do tamanho da visualização, mas um seja como um tamanho estático e o resto apenas se expanda E então eu vou colocar isso um pouco mais no canto ali. Vamos clicar em Play. E veja como isso acontece. Ok, isso é muito melhor, tamanho mais apropriado. Então, é claro, só para testar novamente. Vamos derrotar um cara, e isso é atualizado, então temos nossos inimigos derrotados contando. Então, vamos adicionar mais uma estatística, que é quanto tempo nosso jogador sobreviveu no jogo, outra estatística útil e boa para nossa pontuação mais alta Então, em nossa visão de Gamests, vou duplicar esse contêiner HBox Agora vamos precisar de um contêiner VBox para que eles possam se sobrepor uns aos outros Clique com o botão direito do mouse em Margin Container e adicione um VBox. Mova essas duas caixas H para baixo dela, assim, e agora altere o rótulo estatístico à esquerda para cólon sobrevivente no tempo E se entrarmos no GameStatsView, será uma configuração muito semelhante Vamos apenas nos conectar às estatísticas de quanto tempo vivemos e mostrar que, na época, a área sobreviveu. Então, vamos clicar com o botão direito do mouse em Estatísticas, procurar o símbolo e abri-lo. Então, vamos fazer com que o tempo de variação tenha sobrevivido, que é uma flutuação igual a 0,0 Vamos definir o valor disso. Nós realmente não deveríamos precisar desse guarda. É só um extra. Então, vou apenas dizer que o tempo sobrevivido é igual ao valor. E então, é claro, o tempo sobreviveu, mudou de emissão, o tempo sobreviveu E então teremos esse sinal aqui no topo. O tempo sobreviveu, mudou. O que será uma flutuação temporal. Ok, então todo o motivo de ter esse guarda é que, se por algum motivo, algo no jogo definiu o valor como o valor em que ele já está, tipo, inimigos derrotados era 50, e agora é 50 novamente. Eu acionaria uma atualização extra da interface do usuário. Mas, honestamente, em primeiro lugar, é improvável que isso aconteça E em segundo lugar, isso realmente não deveria dar grande importância a nada. Portanto, é mais do que apenas com base em detalhes técnicos. Isso só muda se o valor realmente mudar, em vez de realmente ser um problema para o jogo. Então, eu só queria esclarecer isso. Ok, agora, nosso reset também precisa levar o tempo sobrevivido e defini-lo 0,0 porque estamos redefinindo o tempo Ok, então vamos ver o que mais? Em nosso mundo de jogo, acho que queremos aumentar o tempo Então, quando o mundo estiver funcionando, teremos um processo de sublinhado de função Vou pegar o gerenciador de jogos dot stats dot TV plus é igual ao Mas isso só pode realmente ocorrer enquanto o jogador estiver vivo. Então, vamos fazer Exportar para o contexto em Exportar contexto VR, contexto do jogador. Você pode ver onde estamos usando esse recurso de contexto em todo o jogo em diferentes lugares. Portanto, ter isso como um recurso salvo é extremamente útil para poder espalhar a referência para toda a nossa interface de usuário e outros nós que precisam referenciar o jogador sem ter uma referência direta à cena do jogador. Então, espero que eu tenha deixado claro o quanto isso pode ser útil. Portanto, temos o contexto do jogador e só queremos aumentar o tempo sobrevivência se o jogador estiver vivo. Então, se entrar em contato com dot player dot stats dot Live , aumentaremos o tempo Caso contrário, vamos simplesmente pular isso. E isso deve ser bom o suficiente. Por enquanto preciso de uma referência ao novo rótulo de quantidade. Então, diremos que em Export var, Time label é um rótulo de rich text, e essa é a visualização GameSts, é claro Então, digamos que o gerente de jogo dot stats dot Time survive change dot Connect, on Time survive, changed. E nós só temos outra ligação aqui embaixo. A função no tempo sobreviveu alterada, obtém o PT float Vamos retornar vazio e, em seguida, colocamos o texto na etiqueta Portanto, o texto do ponto do rótulo temporal será igual a uma sequência de caracteres do PT, e isso provavelmente é bom o suficiente. Também vou fazer uma declaração sobre o cronograma . Verifique se está configurado. É necessário definir o marcador de tempo para atualizar o tempo sobrevivido. OK. E em nossa visão de jogos, vamos atribuir esse outro rótulo de valor Talvez queiramos renomear esses contêineres HBox. Então, o primeiro contêiner foi o contêiner derrotado pelo inimigo. E então o segundo é o contêiner que sobreviveu ao tempo. Então, apenas esclarecendo qual é qual. Vamos garantir que esteja na interface de jogo. Vamos sair para o mundo, ver se ele ainda está lá. Clique em play para testar e executar e ver como isso vai ficar. Ah, ok, então eu não defini o contexto do mundo, é claro. Então, no nodo mundial, temos que carregar rapidamente o contexto do jogador. Está bem? E agora, se corrermos, o tempo deve ser capaz de aumentar. E então temos o tempo lá em cima, no canto superior direito. Agora, isso está funcionando principalmente. Acho que há alguns problemas aqui. Primeiro, parece que precisamos expandir isso um pouco mais verticalmente Oh, bom. Quando o jogo é positivo, ele também para. Isso é importante. E então, em segundo lugar, não acho que precisamos mostrar todos os milissegundos. Acho que reduzir isso para uma casa decimal seria um pouco menos estressante Você pode ver que a segunda e a terceira casas decimais estão Você nem consegue lê-lo. Portanto, não adianta mostrar essas informações. Ok, então, para alterar nossa função de configuração de texto, vamos fazer a cotação por cento um F. Então, isso nos dará o valor flutuante com uma posição decimal e, em seguida, forneceremos um símbolo de porcentagem para adicionarmos a variável PT para realmente configurar essa adicionarmos a variável PT para realmente configurar Ok, e agora podemos clicar em play e veremos que a hora mostra apenas a primeira casa decimal Isso é dez vezes mais legível e menos perturbador. Grande atualização. Então, acho que está ótimo para nossas estatísticas de jogo. Acho que a única coisa que eu poderia mudar é colocar o tempo sobrevivido no topo e o inimigo ser derrotado na parte inferior e clicar em jogar mais uma vez. Acho que vai ficar um pouco melhor. O tempo sobreviveu. Acho que quero a mais chamativa no canto superior direito e, em seguida, as outras estatísticas menores mostradas abaixo dela, aquelas que serão menos atualizadas Aqui está apenas uma pequena preferência visual. OK. E só para mostrar que ainda podemos derrotar o orc, e isso impede o funcionamento. Portanto, as estatísticas do jogo são boas , pelo menos na jogabilidade. 59. L58 Como salvar e carregar partituras altas com JSON: Ok, agora que nossas estatísticas de jogo estão funcionando, queremos pegar isso e, em caso de derrota, queremos atualizar as pontuações mais altas e salvá-las em um arquivo JSON Então, isso seria basicamente o início de um sistema de salvamento de carga. E nesse tipo de jogo, especificamente, não existe tanto um estado de salvamento quanto apenas pontuações altas, mas o processo seria muito semelhante se você precisasse salvar um arquivo de jogo. Basicamente, você precisa serializar os dados em um arquivo, e uma das maneiras mais convenientes fazer isso é o formato JSON Portanto, para salvar e carregar os dados, quero ter um objeto de salvamento e carregamento. Agora, normalmente, eu faria disso um sistema separado, mas a única vez que precisamos salvar os dados é quando nosso personagem é derrotado, e vamos lidar com isso por meio do gerente do jogo. Então, na verdade, vou criar um novo script nos sistemas criar um novo script e chamá-lo de save load. Não vou chamá-lo de sistema porque é mais um componente do próprio gerenciador de jogos. E isso será contado por referência. Então, vou criar esse script. Vamos expandir os sistemas. Abra-o. Poderíamos dar a ela o nome da classe save load. E vamos precisar de duas funções aqui: função de salvar estatísticas, e isso vai usar as estatísticas atuais do jogo como parâmetro. Então, estatísticas das estatísticas do jogo, e retornaremos nulos aqui Então, isso pegará as estatísticas atuais e transformará em um dicionário de dados e, em seguida, serializaremos esses dados Então, os dados de VR são iguais a e eu coloco e coloco entre colchetes aqui no Colon, estatísticas com dois pontos Agora, esse método, é claro, não existe. Escreveremos isso em um minuto. E uma vez que temos os dados em um dicionário, este é um dicionário de dados, a propósito, eu poderia deixar isso mais claro declarando o tipo lá Mas sempre que você vê esses colchetes e o script GD, você está falando sobre Então, em seguida, transformamos esses dados em uma string JSON. Então, isso também é muito simples de fazer. Diremos que var JSON string será igual a JSunnu. Portanto, temos um novo objeto JSON que nos permite chamar essa string do método Pi em nossos dados, e isso a torna em um formato de string JSON legível em JSON Então, agora precisamos abrir o caminho do arquivo. Então, diremos que var file será igual a fileaccess dot OP Portanto, essa é outra classe estática na biblioteca Godo, e precisamos fornecer a ela um caminho e, em seguida, o acesso correto ao arquivo Então, vamos dizer Save File path, que ainda não definimos, e então queremos acessar aqui. Então, onde vamos obter o caminho seguro do arquivo aqui no topo? Diremos var, salvar o caminho do arquivo é uma string. Isso será igual ao usuário slash LASH gametatt JSON. Ok, então o que esse Fopath basicamente significa é que ele salvará os dados do aplicativo, supondo que você esteja no Windows, para esse projeto de jogo específico, na raiz dessa pasta, haverá um novo arquivo chamado gamesatt Então, cada jogo feito no GADO tem uma pasta de usuário no Windows, essa é a barra de dados do aplicativo Gdolah, o nome do seu projeto, E então ele salvará o JSON do GameStatst na raiz. Portanto, esse arquivo JSON é efetivamente seu arquivo salvo. Para um jogo de sobrevivência, o arquivo say é, na verdade, apenas suas estatísticas mais altas porque toda vez que você inicia um novo jogo, você tem um novo personagem, não salva e carrega o jogo como faria com um RPG típico Mas o processo é mais ou menos o mesmo. Então, se o arquivo existe e tivemos que abri-lo para gravação, correto? Então, se não o encontrarmos, então deve ter ocorrido um erro. Mas se a encontrarmos, diremos file dot store string porque temos uma string JSON lá em cima, certo, então apenas armazenamos a string JSON no arquivo e, em seguida, fazemos file dot E é assim que você grava no arquivo. Caso contrário, se a operação correta estiver falhando, claro que queremos pressionar e errar Portanto, o erro push falhará ao abrir um arquivo para gravação, e eu poderia dizer no caminho, por cento s, e faremos as cotações Então aqui, porcentagem do caminho do arquivo salvo. Então, fornecendo o máximo de informações possível, e então podemos depurar a partir daí se houver algum problema Obviamente, você precisa soletrar porti error corretamente. Isso ajudaria, e essa é a função segura. Ok, agora queremos fazer nossa função de carregamento de estatísticas. Então, a função carrega as estatísticas e teremos o objeto de estatísticas no qual estamos carregando os dados. Portanto, as estatísticas são do tipo estatísticas do jogo. Claro, receberemos isso do gerente do jogo mais tarde. E primeiro, queremos abrir o arquivo para o R acessar. Então, o arquivo VR é igual a Deus, não consigo digitar agora. O arquivo VR é igual a fileaccess dot OP no caminho do arquivo salvo Então, estamos carregando e salvando no mesmo caminho de arquivo. E então temos o Fleaccess dot RED. Então vamos. Então, digamos que, se não for arquivo, então falhamos em abrir, podemos dizer, erro push, falha ao abrir o arquivo para leitura em Path percentents, percent, save file Talvez até queiramos fazer disso um booleano. Portanto, se o tornarmos um booleano , podemos retornar false aqui, pois falhamos na operação Isso pode ser um pouco mais útil. Posteriormente, você pode alterar Safsts para fazer a mesma coisa, se quiser E estamos retornando false, não literalmente a palavra-chave, então, neste momento, nossos arquivos estão abertos para acesso de leitura. Então, agora precisamos obter a string do arquivo JSON. Portanto, nosso JSOText é igual ao arquivo dot Get as text. OK. E a razão pela qual isso não está aparecendo é provavelmente porque eu não digitei isso aqui. Então, eu poderia dizer acesso a arquivos. Vamos ver, o texto JSON também deve ser sublinhado lá, e podemos continuar Então, temos o texto do arquivo, então terminamos com o arquivo. Vamos fechar o arquivo, fechar o filé. Se o arquivo estiver vazio , podemos voltar aqui. Portanto, o texto com pontos JS está vazio. Então você pode retornar verdadeiro ou falso aqui. Depende do que você quer. Vou retornar true, na verdade, para que possamos indicar que a operação foi bem-sucedida, mas não havia dados para carregar Então, vamos dizer que carrega os dados de estatísticas no objeto de estatísticas do jogo. Portanto, se o arquivo não estiver vazio, precisamos convertê-lo. Até agora, JSON será igual a Jsunt Nu. Portanto, temos um novo objeto JSON e, em seguida, queremos analisar o texto Então, digamos que var error seja igual análise de pontos json no Então, se houver um problema com isso, retornará um erro. Então, em caso de erro, queremos enviar um erro, falhamos em analisar o JSON com porcentagens de erro, e eu direi Acho que isso pode acrescentar algumas informações extras úteis. E então retornamos false aqui porque, é claro, se ele errou ao analisar o arquivo, então há um grande problema com nosso arquivo SAI Provavelmente não foi formatado corretamente. Ok, então se não houve erro, sabemos que a análise funcionou corretamente, então podemos dizer var Um dado do dicionário é igual aos dados json dot g. Então, estamos basicamente transformando-o no formato GIDorCognized E então diremos que os dados de Varsats são um dicionário igual ao ponto de dados. Entre na cotação Stats, E o padrão aqui é um dicionário vazio. Então, essas estatísticas devem corresponder às que temos aqui. Salvamos as estatísticas no par de valores-chave e precisamos recuperá-las do par de valores-chave de estatísticas Então, quando tivermos nossos dados estatísticos reais, que são um dicionário, podemos fazer stats dot From dict for dictionary, e passaremos os dados estatísticos. E isso é tudo o que precisamos fazer para nosso carregamento, então retornamos verdadeiro. Ok, eu acho que isso parece muito certo. Então, o que precisamos agora é de um método de dois dicionários e do dicionário from para nossas estatísticas de jogo. Então, se abrirmos as estatísticas do jogo, digamos que function to dict retorne um dicionário e, em seguida, a função de dict pegue um dicionário de dados e retorne void Então, para transformar isso em um dicionário, precisamos que um dicionário de realidade virtual como esse seja igual a um novo dicionário. E então, na verdade, você sabe, dentro daqui, podemos simplesmente colocar tudo isso em uma coisa e colocar cada novo par de valores-chave em uma nova linha. Então, diremos que inimigos derrotados são iguais a inimigos derrotados. CD de dois pontos para o par de valores-chave. À esquerda, você tem o nome da string e, à direita, o valor real. Então, à esquerda, temos sobrevivido ao tempo. E então dois pontos, e tempo sobreviveu até a variável à direita, e então retornamos o dicionário E é realmente muito simples. Então, a seguir, do dicionário, queremos carregar os valores antigos nos valores atuais. Então, vamos fazer com que inimigos sejam derrotados, igual a p data dot git, o par de valores-chave E então, o valor padrão, vamos torná-lo nulo para que, se não houver esse valor, obtenhamos um erro porque caso contrário, o carregaríamos em algo como zero, e isso substituiria permanentemente todos os nossos dados salvos É meio discutível qual caminho você quer seguir aqui. Por exemplo, você quer que ele falhe imediatamente no carregamento do salvamento ou que seja bem-sucedido, mas depois substitua os dados reais antigos, que realmente não parece muito desejável, certo? Você não quer anular o progresso do jogador. Então, talvez seja mais como se você precisasse lançar um hot fix ou algo parecido. Se você se deparar com essa circunstância em que o JSON simplesmente não carregou corretamente, você não tem esse campo, está faltando o nome, algo assim Então é por isso que eu estou indo mais ou menos assim: Oh, deveria ser nulo Então, quando ele tenta definir o float como nulo ou o inteiro como nulo, você encontrará um erro e ele precisará ser corrigido ou, caso contrário, interromperá todos os jogos de Acho que esse é provavelmente o caminho a percorrer aqui. Então, time survived será igual a pdta dot get on time survived como uma string, e então o valor padrão é Ok, então temos as estatísticas do jogo Atualmente, as únicas estatísticas do jogo são as estatísticas principais do jogo, estatísticas atuais do jogo, mas também queremos ter estatísticas de jogo persistentes, nossas estatísticas de jogo com maior pontuação. Então, eu quero colocar uma função aqui para obter o valor mais alto em comparação com as estatísticas atuais do jogo. Então, vou dizer que a função está configurada para a maior, digamos, definir pontuações mais altas. Para as estatísticas atuais do jogo P, e isso será anulado Então, vamos chamar isso apenas nossas estatísticas de jogo com pontuações mais altas, mas basicamente consideraremos o maior dos dois valores. Portanto, os inimigos derrotados serão iguais ao máximo de inimigos derrotados ou ao ponto P atual de inimigos derrotados. Ok, então estamos apenas pegando o valor mais alto e configurando-o para os inimigos inteiros derrotados E fazemos a mesma coisa com o tempo sobrevivido. O tempo sobrevivido é igual ao máximo. O tempo sobreviveu e o ponto P atual, o tempo, sobreviveu. Ok, então é assim que obtemos as pontuações mais altas. Apenas comparamos as estatísticas atuais no final do jogo e vemos se maiores do que nossas pontuações mais altas atuais. Portanto, precisamos do objeto de salvamento e também das estatísticas de jogo com maior pontuação em nosso gerenciador de jogos. Então, vamos abrir o gerenciador de jogos agora. Gerente de jogo dot GD. Então, também teremos aqui as estatísticas de pontuação mais alta, que serão um GamestStnu e também teremos aqui o var saveoad, que será igual ao nosso objeto save será igual ao nosso Portanto, esse é apenas um componente local do nosso gerenciador de jogos. Talvez até o tornemos privado. Sim, por que não? Torne-o privado. Porque, na verdade, na lógica do saveoad, queremos pertencer apenas ao gerente do jogo Na verdade, não é algo que outros scripts deveriam abordar, então nós o tornamos privado Então essa função aqui, digamos que a função End Game, acho que é um pouco melhor renomear Isso será anulado. Então, no final do jogo, queremos obter nossas estatísticas de pontuação mais alta e definir pontuações altas com nossas estatísticas atuais. E então talvez queiramos redefinir as estatísticas atuais, mas na verdade não vou fazer isso porque talvez queiramos mostrar no menu principal do jogo quais foram as pontuações da última sessão, para que não reiniciemos o jogo corretamente até reiniciarmos o jogo corretamente. Acho que é um pouco melhor. Ah, e é claro, depois de estabelecermos as pontuações mais altas, queremos chamar save load dot save stats. Então, vamos salvar as estatísticas de pontuação mais alta. E acho que está pronto. Sim, na função Ready. E lembre-se, isso é Auto Load Singleton, então, assim que o jogo começar, ele já estará E eu quero fazer o sublinhado salvar as estatísticas de carregamento de pontos nas estatísticas de pontuação mais alta E sim, isso realmente lida com o resto. Portanto, a fila lógica para salvar e carregar está basicamente escondida dentro desse objeto de salvamento ou, na verdade, está encapsulada Portanto, toda a carga de salvamento está aqui, mas o gerente do jogo realmente determina quando deve salvar e carregar esses dados. E você pode ver que isso torna o gerenciador de jogos muito mais fácil de ler porque dividimos suas funções em componentes diferentes, em vez de amontoar tudo em um script gigante de gerenciamento de jogos Portanto, este vídeo está um pouco longo, então farei o próximo vídeo sobre como criar a tela do menu principal. Já temos o modelo para ele porque nosso botão de fim de jogo vai até aqui, mas não configuramos nada aqui Então, vamos conectar isso às estatísticas de pontuação mais alta , ter uma tela, um botão Iniciar o jogo e algum tipo de fundo de tela inicial 60. Parte 59 Como projetar um menu principal com exibição de alta pontuação e funcionalidade de início de jogo: Vou pegar o layout no contêiner High Scores e colocá-lo nas âncoras da parte superior ou direita. Então eu posso ampliar. Vou pressionar Q para mover essa posição para lá. Vamos ampliar nosso contêiner de pontuações mais altas e, em seguida, criaremos alguns outros nós de controle aqui. Então, vou clicar aqui e adicionar um nó filho. Digamos que Margin Container. Mesma história com o contêiner Margin. Queremos uma substituição de tema, quatro pixels em todos eles E então, para economizar tempo, acho que poderíamos acessar a visualização de Gamesets. E vou copiar e colar que o tempo sobreviveu e os inimigos foram derrotados. Vou apenas controlar a visualização de tudo e colar no menu principal. Então, dentro de lá. E eu esqueci um contêiner VBox, então adicione um contêiner VBox e mova esses dois contêineres de texto para baixo dele. Assim. E então é mais ou menos assim que vai parecer agora. Vamos salvar o contêiner de pontuações mais altas em sua própria cena, clicar com o botão direito do mouse, digamos cena branchien, assim E então eu quero transformar o layout e triplicar a escala, desse jeito. Ok, então quando fizermos isso, vai mexer um pouco com nossa predefinição de âncoras, então vou posicionar isso ali Não há necessidade de deixá-lo realmente perfeito. Também vamos abrir o contêiner de pontuações mais altas e adicionar um texto de título. Então, ampliando aqui o contêiner do VBox, clicarei com o botão direito do mouse e adicionarei um rótulo de rich text E vamos posicionar isso em cima do contêiner VBox. Confira o conteúdo do Fit e , digamos, as pontuações mais altas, mas vou começar com, digamos, arco-íris Termine os colchetes, vá até o final Rainbow Obviamente, para que isso funcione, precisamos verificar se o código BB está ativado e obtemos um arco-íris padrão Então, acho que quero diminuir a frequência e tornar isso menos dramático. Então, digamos que a frequência seja igual a 0,5. Bem, vamos até 0,25. Sim. Isso é muito melhor. E então precisamos do SAT para saturação. Então, digamos que saturação de 0,2, talvez 0,5. Ok, isso é um pouco mais manso. Então isso é bom. E faremos o centro de alinhamento horizontal. Ok, isso não é tão ruim. Então, no menu principal, podemos ver como isso vai ficar. De volta ao contêiner de pontuações mais altas, vamos atribuir o rótulo correto. Portanto, o rótulo máximo derrotado é o rótulo da quantidade sob o contêiner derrotado do inimigo. E então o rótulo que sobreviveu por mais tempo está no recipiente que sobreviveu Ok, salve isso e, de volta ao nosso menu principal, precisamos de um fundo de textura. Então, vou clicar com o botão direito do mouse no menu principal. Vamos adicionar um ato de textura. Vou renomear isso para ter o plano de fundo destruído. Voltaremos a isso. Além disso, na tela do menu principal, queremos ter certeza de que desativamos a filtragem do mouse Então, passe o mouse à direita, giramos o filtro para ignorar. Isso é importante. Caso contrário, o menu principal realmente bloquearia os botões abaixo dele. Então, vamos adicionar um botão agora para o nosso jogo Iniciar. Então, adicione um botão. Vamos renomear isso para o botão Iniciar jogo. E se bem me lembro, eu só tenho um roteiro que pode mudar de cena imediatamente. Então, botão de mudança de cena, vou arrastá-lo e soltá-lo diretamente no botão Iniciar jogo. E então precisamos dar a ela a trajetória cênica do mundo. Então, no canto superior direito, caminho da cena, selecione o ponto mundial TCN, e agora esse botão deve ser capaz de abrir o mundo, que é a nossa cena de jogo Esse botão é muito pequeno, é claro, então precisamos ir para o layout. E eu vou triplicar a balança aqui embaixo. Vamos também posicioná-lo em âncoras e, em seguida, dizer no centro da parte inferior. Podemos ampliar aqui. Eu vou bater em W. Vamos mudar isso até aqui. Vamos dar a ele o texto Iniciar jogo, e talvez queiramos selecionar um ícone também. Então, vamos criar ícones como textura de atlas, carregamento rápido e atlas do nosso projeto de jogo Eu vou fazer 64 ou 64. Escolha a região e escolha o ícone que quiser para começar o jogo. Então eu não sei. Como este é um jogo baseado em combate, talvez uma dessas espadas seja boa Então, vou pegar isso, certificar de obter todos os pixels. Então eu preciso esticar isso para a esquerda, apertar. Por precaução, eu também vou verificar o clipe do filtro. Não queremos que pixels de borda entrem lá. Então esse é basicamente o nosso jogo inicial. Pressione o botão W e verifique se está dentro dos limites do nosso menu principal Vamos também ao Projeto, e vamos pegar o menu principal e fazer dele nossa cena de lançamento do jogo. Então, em geral, corra, em vez de lançar o mundo agora, vamos carregar. O menu principal tem pontos TSCN. Ok, agora vamos ver onde estamos. Vou clicar em play. a pontuação mais alta lá em cima, temos Start Game. Vamos clicar em Iniciar jogo, que inicia nossa cena principal de jogo. Isso é o que esperaríamos. E rapidamente, na verdade, vamos ser derrotados para que possamos ver a pontuação mais alta em nosso menu principal. Claro, eu renomeei o Game Manager dot report game over, então precisamos mudar isso para game manager dot end game Isso está no estado do jogador derrotado. Ok, agora vamos lançar mais uma vez. Então, vou me certificar de ser derrotado por uma dessas obras, três acertos, quatro acertos, cinco acertos. E vamos ver. Os jogadores já foram libertados. Está na nota mundial porque, na verdade, libertamos o jogador Também precisamos dizer aqui para todos os mundos. Se o processo funcionar, onde estamos adicionando o tempo sobreviveu, teremos que dizer se o contexto está fora do jogador. E teremos que dizer que não é igual a nulo. Acho que para referências liberadas anteriormente, se você apenas usar o Context Out player, ainda haverá um erro, mas se você disser que não é igual a nulo , isso contornará isso Ok, então, basicamente, se o jogador não existir mais ou não estiver mais vivo, adicionaremos o tempo de sobrevivência às estatísticas do jogo. Como o player foi removido, isso resolverá essa parte , e devemos estar prontos para começar. Ok, então mais uma jogada de rebatida, certificando-se de que realmente funcione Oh, podemos ver que a pontuação máxima foi atualizada aqui, então isso é bom. Talvez precisemos redimensionar um pouco a interface do usuário. Como você pode ver, o problema aqui está mostrando cerca de 12 pontos decimais, então vamos mudar isso em um minuto Vamos ver se podemos ser derrotados em menos de 7 segundos. Ok, vamos. Um, dois, espere. Atualize este equipamento e ele falhou. OK. Então, temos que encontrar outro inimigo ou dois. Lá vamos nós. 12 segundos. Menu principal. Você pode ver que nossa sobrevivência mais longa agora é de 12,6 segundos. Os inimigos derrotaram dois. E vamos fechar o jogo e clicar em play. Isso verificará se o carregamento do arquivo está realmente funcionando. Então, vamos fechar e clicar em play. Talvez eu ainda não o tenha configurado. É interessante ver se tem ou não. Ok, então sim, quando o jogo carrega, o gerente do jogo é, tipo, uma das primeiras coisas a carregar, e ele já carrega na pontuação máxima qual é a pontuação máxima salva do arquivo. Ok, então, como um bom momento para mostrar onde isso está, vamos apresentar os dados do aplicativo no Windows File Explore e, em seguida, queremos encontrar Godot E então eu acredito que são os dados do usuário do aplicativo, o script GD do Script Survivor mais recente do projeto E aqui temos o Arjsofle. Ok, então vamos editar no Bloco de notas. E aí você pode ver ali mesmo. Nossas estatísticas reais do jogo foram salvas em um arquivo. Temos inimigos derrotados duas vezes e sobreviveram a 12,6, e esses são nossos dados de jogo salvos, que são atualizados sempre que somos derrotados, caso tenhamos algum desses números Ok, então para o contêiner de pontuações mais altas, o texto sobrevivente mais longo, nós meio que queremos copiar o que estávamos fazendo na visualização de estatísticas do jogo Então, vou entrar nesse roteiro. E então eu quero copiar essa parte aqui, que pega o fluxo e nos dá uma string que tem apenas uma casa decimal Vá para o contêiner de pontuações mais altas, e eu vou substituí-lo aqui por este. O PT, é claro, será na verdade o gerente de jogo dot high scorstts dot Time Agora, se estivermos jogando, chegarmos ao menu do jogo, devemos ver 12,6 segundos aqui Isso é muito mais legível do que nossa pontuação mais alta. Então, agora, para nosso histórico, vou literalmente fazer uma captura de tela do jogo E você pode desativar a interface do usuário para isso se quiser fazer uma captura de tela Isso provavelmente seria um pouco mais útil. Ok, então vamos também desativar as formas de colisão antes de fazer a captura Então, depure as formas de colisão. Ok, então vamos pegar nosso site como uma atualização para que possamos mostrar isso. Vou deixar alguns desses captadores no mapa do jogo. Vamos esperar que o esqueleto apareça e depois veremos se podemos obter uma boa captura Uma coisa que eu consideraria seria aumentar a taxa de desova se quisermos enfatizar quantos inimigos existem no jogo Ok, então vamos capturar a tela aqui. Eu não gosto muito desse. Vamos talvez fazer uma captura de tela lá. Então, imprima a tela para fazer uma captura de tela, se isso não for óbvio E eu vou abrir a Gap. Então, o Gap é um editor de imagens gratuito. É como o Photoshop. Mas grátis. Então vamos fazer File New, e eu vou fazer 1920 por 1080 pixels. Abra isso. Controle V para colar nossa captura e vamos pegar algo parecido Não é realmente um tutorial de edição de imagens aqui, mas bem rápido, vou colar uma barra superior lá. Então, usando um preenchimento preto, podemos fornecer o texto, se assim o desejarmos. Vou escolher uma fonte. Então, vamos usar o pixel regular. Você teria que instalar essa fonte se quiser usá-la. Ok, então eu passei um pouco de tempo criando uma espécie de miniatura personalizada, exceto que vamos usá-la no projeto final do jogo Então, basta colocar em um fundo preto na parte superior, um texto da Pixar, mencionando que é um curso GD, mencionando que é um curso Do e, em seguida, o ícone Gudo Essa provavelmente não será a miniatura final do curso, mas podemos usá-la na tela do menu do jogo, pelo menos por enquanto E eu vou abrir isso. Eu o exportei para o projeto, é claro. Então, onde você salvou isso, você pode ver que eu tenho a tela do menu principal aqui. Então, o que eu quero fazer e a interface do usuário, essa é, na verdade, a tela errada. Queremos o menu principal. Vamos para o fundo Rec Vou carregar rapidamente e procurarei a tela do menu principal. Coloque isso aí. Talvez eu precise aumentar o tamanho aqui, então vamos para o modo de layout, âncoras e destruímos completamente Ok, então com isso e totalmente destruído, agora queremos ter certeza de que nada seja bloqueado por Então, acho que precisamos mover isso para o topo à esquerda. Ok, aí as pontuações mais altas mostram que podemos jogar. Ok, e podemos jogar, e devemos vê-lo lá. pontuação mais alta de Script Survivors aqui . É um curso de Gado. Temos o botão Iniciar Jogo e o ícone Gado, que, quero dizer, são bastante sólidos para cerca de cinco, 10 minutos de trabalho, acho que, é claro, podem ser melhorados. Ok, agora, neste momento, praticamente o jogo está quase pronto. Temos nossa tela inicial lá. Podemos começar o jogo, as pontuações mais altas, exibidas durante o jogo as pontuações atuais e na tela do menu principal, as pontuações mais altas de todos os tempos. Nós podemos derrotar os inimigos. Podemos perder o jogo. Podemos atualizar, talvez queiramos fazer alguma limpeza, como remover essas atualizações iniciais do mapa do jogo Isso é um pouco estranho lá. Mas isso estava lá apenas para fins de teste. Talvez queiramos aumentar a dificuldade, adicionar novos inimigos Poderíamos ter nosso personagem principal, você sabe, mostrando a lança se quisermos que ela esteja lá, em vez de meio que sem braços Mas, quero dizer, funciona do jeito que é agora. E podemos subir de nível várias vezes. Não está pronto para o lançamento completo, é claro. Ainda haveria muito trabalho a ser feito lá, mas tudo está basicamente funcionando conforme o esperado. Acabou o jogo. Aí está nossa pontuação mais alta. Talvez o menu principal possa usar uma trilha sonora, que eu possa fazer para que eu possa fazer mais um vídeo aprimorado limpar o curso, para limpar o curso, mas é basicamente isso Então, espero que todos vocês tenham aprendido muito até o fim. Eu sei que foi um curso bem longo, 11 horas mais o tempo de execução total editado. Então, quero dizer, se você chegou aqui e acompanhou tudo e seu jogo está funcionando como está, quero dizer, bom trabalho porque na verdade foi bastante. Ok, então muito obrigado por assistirem, grosso modo, o final do meu curso de sobreviventes de roteiros, roteiro GD em Gadot 4.4 61. P60 Aperfeiçoamento de sobreviventes em script ~ Melhorias de jogabilidade e depuração: Então, neste vídeo, vamos tentar aprimorar o protótipo do nosso script Survivor Então, primeiro, no final do último vídeo, eu tenho sete erros no console. Então, essa é a primeira coisa que vamos cuidar. Sempre que você vê um erro, é um bom momento para resolvê-lo, depurá-lo e descobrir o que estava errado Portanto, temos itens retirados que não têm um item realmente atribuído a eles Então eu acho que o que seria realmente útil aqui seria dizer porcentagem Sul, e então colocamos isso aqui como porcentagens Ok, então você pode ver que a mensagem de erro aqui não é tão clara quanto poderia ser. retirada de um item precisa ter um item, mas não sabemos qual item realmente falhou na coleta Então, como você pode fazer isso no script D de coleta de dois itens é, no final do script atribuído à coleta, fazer uma porcentagem e, em seguida, seguir a sequência com Então, isso substituirá as porcentagens pelo nó, que será resolvido para um nome de nó ou, em outras palavras, qual nó realmente não teve o item atribuído Ok, vamos fazer isso mais uma vez. Vou jogar um pouco, ver se encontramos novos problemas. Ok, então, como esses itens são retirados e a parte de saúde, diz que o item não está pronto, que é estranho, porque a exportação na exportação definitivamente deveria estar fazendo isso Portanto, se o item for igual a nulo , relataremos um erro Oh, ok, certo, certo. Então eu cometi um erro aqui. Se isso fosse uma afirmação, funcionaria bem. Mas o que realmente queremos fazer é dizer que o item I é igual a nulo e, em seguida, inserimos o erro Eu ainda estava na lógica assertiva lá. Então, vamos acabar com isso. Se o item for nulo, enviaremos um erro. Agora, se jogarmos, deve funcionar, é claro. Caso contrário, sempre geraria um erro. Então, você pode ver no debugri aqui embaixo que não há problemas Vou coletar alguns itens. Vamos fazer com que os inimigos os derrubem, e isso deve funcionar muito bem para isso. Até agora, não parece que haja outros erros novos. Eu notei um pequeno problema de layout da interface do usuário aqui. Então eu acho que se eu pegar a foice aqui, ela pode meio que reposicionar essa interface de usuário de alguma forma estranha Oh, ok, isso é o que aconteceu. A caixa HB estava, na verdade, se expandindo para ficar maior. Então, para corrigir isso, eu preciso bloquear o tamanho no lugar. Caramba, eu deveria torná-lo maior e depois mover isso para a direita. Acho que seria melhor. Ok, então, para essa interface de jogador, precisamos expandi-la um pouco para que ela tenha espaço para grelhar. Então, vou entrar na interface do jogador. E então vamos pegar o contêiner do painel raiz esticá-lo para a direita para que ele tenha espaço extra. Vou para a interface do Game Play. Vamos mover isso para a direita. Agora, se eu clicar em Play e por acaso melhorarmos nossa saúde, e ele a redimensionar, ele não deve mais empurrá-la para a direita, porque ela já tem espaço para caber no rótulo de texto completo E eu preciso redimensionar um pouco o layout das armas. Eu o comparei um pouco incorretamente, então vou alinhar isso até o topo, clicar em jogar, começar Ok, e isso parece bem sólido. No mundo, eu quero remover todos esses captadores por padrão Eram só para testar. Eles não deveriam estar no protótipo final, então vou cortá-los com o Control X, selecionando todos E acho que quero tornar o jogo padrão um pouco mais difícil. Então, vou para o sistema de geração e vamos aumentar a taxa de amplitude Então, vou reduzir isso no início para uma taxa de desova mais alta Adicione também um ponto extra aqui, mais ou menos assim. Ajuste o guidão, algo parecido. Eu só quero fazer uma curva mais íngreme para que mais inimigos apareçam mais rápido para que eu possa mostrar uma jogabilidade mais intensa Na demonstração. Está bem? E todos jogam. Vamos testá-lo um pouco e ver como funciona. Então eu vou começar o jogo. Queremos que nossos inimigos cheguem ao centro. Talvez os orcs sejam um pouco lentos demais. Eu poderia aumentar a velocidade de movimento dos orcs e do esqueleto Portanto, não há realmente nenhuma necessidade de facilitar as coisas aqui. OK. Então, aí temos nossos esqueletos e os orcs Então, vou aumentar a velocidade de movimento dos dois. Vou procurar o controlador estatístico orc . Vamos mudar as estatísticas dos orcs. A velocidade pode ser, digamos, 35, e então vamos até o esqueleto Velocidade do controlador Sat de 60. Vou dificultar as coisas aqui, e então o MX HP pode chegar a 100. Tudo bem. E o HP orc é 40. Tudo bem. Vamos jogar. Comece o jogo. Uma coisa que você pode acrescentar: eu não vou fazer isso aqui, mas ter, tipo, uma explosão de inimigos no início tornaria a jogabilidade inicial um pouco mais intensa se você começasse o jogo gerando instantaneamente dez caras para virem até Isso pode ajudar. Mas acho que isso é um pouco exagerado apenas para o protótipo Então, as obras se movem um pouco mais rápido, e os esqueletos estão bem rápidos agora Então, isso definitivamente será muito mais difícil. Eu preciso pegar o HP atual e configurá-lo para 100 no início. Ok, talvez os esqueletos sejam até um pouco rápidos demais, honestamente Ok, então vamos fixar o HP inicial dos jogadores, o jogador, controlador de estatísticas, as estatísticas do jogador e o HP até 100 E vou acalmar um pouco os esqueletos. Digamos que 50 velocidades. Eu acho que isso é muito justo. Ok, nas definições do nível do jogador, também vou facilitar a subida de nível. Então, vou pegar o nível três e definir isso para cinco. nível quatro será dez XP, o nível cinco, pode ser 15, o nível seis, pode ser 20 e o nível sete pode ter 25 HP. E então vou adicionar mais um para 100. E isso vai ser como aquele que você realmente não conhece. Na verdade, vamos adicionar mais um. Digamos que 1.000 novos níveis de definição. A razão pela qual estou dificultando minha ida é para que isso realmente não aconteça. Eu meio que estraguei tudo. Ou seja, o nível 1.000 leva dez XB. Não é isso que eu quero. O que eu queria, e vamos excluir isso, é que o nível nove será uma definição de nível com 1.000 EXP necessários, acrescente isso Então, isso faz com que eu não precise planejar essa quantidade de escala na demonstração do protótipo Seria um pouco exagerado por enquanto. Então, vamos clicar em Play e eu vou ver como o jogo se desenrola. Comece o jogo e esperaremos que os primeiros inimigos apareçam Ok, eu acho que é um pouco fácil demais no começo. Eu quero que seja intenso rapidamente. Então, acho que o que vou fazer é realmente criar aquela geração instantânea de dez caras Então, no mundo, digamos que, ao exportar V, os spawns iniciais, e eu definirei isso como N igual a dez O mundo terá uma referência ao de geração, portanto, sistema de geração E então, quando estiver pronto, direi os intervalos iniciais estão acima de zero Então, diremos sistema gerador. Deixe-me ver. Como foram chamadas as funções? Spawn aleatório. E eu ligo para isso dez vezes? Espere um pouco. OK. Sim, e parece que preciso ligar para isso dez vezes ou o número de intervalos iniciais. Então, por um tempo nos spawns iniciais, vamos chamar spaorsystem dot Então, dez spawns iniciais, isso deve nos fazer gerar dez caras no início do jogo Ok, não se esqueça de definir o sistema de patrocinadores no mundo. Então, atribua esse sistema de patrocinadores. Referência direta do nó, vamos clicar em Play. E se isso funcionar, teremos dez caras no início do jogo, o que deve tornar tudo muito mais difícil Ok, sim, são muitos caras para o início do jogo. Então, só temos que evitar todos eles. Isso pode realmente ser muito difícil, honestamente. Eu vou reduzir isso para cinco, e vou mudar isso para cinco no roteiro, também. Acho que dez caras no início, quando você ainda nem subiu de nível , é muito lidar com uma só vez Ok, então temos nossos cinco caras começando agora. Vamos pegar um XP. Vou me atualizar com o Syth, o que nos dará maneira extra de atingir os inimigos. Muito mais fácil agora. E eu vou continuar aqui. Vamos fazer algumas atualizações, já que facilitamos muito a curva de EXP, então poderemos subir de nível com bastante Mas devo dizer que aumentar a velocidade dos inimigos definitivamente torna muito mais difícil evitá-los, então isso é algo a se ter em mente Vamos continuar atualizando a lança. Então eu acho que em um certo nível, a lança atinge dois caras ao mesmo tempo. Já está lá. A lança de nível três pode atingir dois caras. O que é definitivamente uma grande atualização. Estou meio que analisando a jogabilidade aqui. Os esqueletos a 50 velocidades são bem resistentes. 60 velocidades para os esqueletos definitivamente seriam demais. Vamos continuar com a lança. Com base nas configurações atuais, na verdade não tenho ideia se a lança ou a foice são melhores Provavelmente com grupos grandes como esse, a foice seria melhor porque, você sabe, ela pode atingir todos eles ao mesmo tempo Mas, às vezes, um único alvo também é importante. Quero dizer, estamos apenas começando a falar sobre como jogar o jogo agora. Então, isso é uma tonelada de esqueletos, e em algum momento, eles vão meio que me pegar Podemos ver um pequeno problema, que é esse tipo de aglomeração excessiva Então, eu quero que eles não se acumulem, mas acho que suas formas de colisão provavelmente são muito grandes agora Isso meio que os torna incapazes de se mover. Então, na verdade, encontramos um bom problema que podemos resolver. Vamos pausar o jogo e depois vou pegar os esqueletos Em todas as cenas, vamos assumir a forma de colisão, e vou reduzi-la bastante Vamos fazer isso como dois e depois vamos até o orc. Vamos tomar sua forma de colisão. Essa é a forma básica de colisão corporal do personagem, e vamos pegar essa forma de colisão, expandi-la e defini-la como duas também Se pararmos de pausar o jogo, se estiver funcionando corretamente, acho que está Não posso dizer 100%. Então, como sua forma de colisão é menor, eles se aglomerarão Mas, sim, ainda é muito difícil quando há tantos caras vindo até você. Se também existissem projéteis, então você definitivamente tem um jogo bem difícil neste momento Para que eu possa comprar mais algumas coisas. Vamos atualizar a foice desta vez. E vamos ver o game over screen. Eu provavelmente poderia correr por um tempo, mas só queremos verificar se tudo ainda está funcionando com o protótipo polido, frutado e sólido que está lá dentro E vamos ao menu principal. Nosso tempo sobreviveu. Acho que preciso trazer isso um pouco para a esquerda para que haja espaço para o ponto decimal neste caso Além disso, acho que estamos muito bem. Então, no menu principal, vou expandir um pouco para a esquerda, colocar tudo em uma linha. Isso vai ficar melhor. E talvez eu coloque a música no menu principal também. Então, vou clicar com o botão direito em um nó. Vamos usar o AudioStream player e não dois D, porque, quero dizer, não há dois mundos D agora Estamos apenas vendo o menu do jogo. Vamos carregar rapidamente nosso AudioStream, então.p3 porque preciso procurá-lo Ok, então vamos adicioná-lo ao áudio agora a partir da pasta de áudio. Temos três Red Hearts Box jump. Também usaremos isso no menu principal. Vou colocar fones de ouvido para poder testar isso sozinho. Vamos jogar. Oh, na verdade eu não reproduzi áudio. Ok, então vamos jogar automaticamente. Sim. E depois jogue. Ok, na verdade, eu quero verificar o mundo principal do jogo, e eu quero ver o quão alto isso é. São -40 decibéis. Ok, então eu até quero que seja um pouco mais silencioso no menu principal Então, vamos fazer com que sejam -45 decibéis. Vou clicar em Play. Teste isso. Ok, e então vamos para Start Game. É um pouco mais alto aqui. Talvez a música de final de jogo eu faça um pouco mais alta do que isso OK. Então, no mundo do final do jogo, eu vou pegar isso e configurá-lo para menos 35 Acho que deixei tudo muito quieto durante o curso porque simplesmente não queria que fosse uma interferência quando eu estava falando sobre isso. Ok, então vamos clicar em Play. começar o jogo. Ok, isso é bom. Outro efeito sonoro que talvez eu queira adicionar é que sempre que abrimos a tela de seleção de aumento de nível, acho que isso poderia usar um efeito sonoro. Além disso, acho que estamos com boa aparência. Então, vamos até a tela de seleção de aumento de nível. Tudo bem, clique em Adicionar um reprodutor AudioStrem aqui. Deixe-me ver se temos alguns bons efeitos sonoros de aumento de nível no projeto. Então, ele estará no menu de interface do usuário de áudio. Claro, deixe-me verificar. Ok, o item de uso parece que funcionaria. Então, vou pegar o reprodutor de stream de áudio aqui. Vamos colocar um item em uso. Isso não será reproduzido automaticamente, então eu preciso ir para a seleção LevelUp. Adicionaremos um pop-up Export var. AudioStream, que será um reprodutor AudioStream. Então, vamos dizer que pop-up audiostream dot play, e eu só tenho que corrigir essa exportação Ok, e então não se esqueça de adicionar o AudioStream pop-up na exportação Então, temos que adicionar isso. Poderíamos fazer uma declaração pronta se quisermos que a declaração apareça no AudioStream. Lembre-se de configurar o reprodutor AudioStream para reproduzir som de nível superior Ok, agora vamos clicar em play. Podemos ir para o Start Game. E vamos testar derrotando um inimigo, subimos de nível. E então fazemos nosso upgrade. A música continua. E eu acho que isso flui muito bem. É definitivamente bom ter um efeito sonoro real para o veo up. Então, vamos continuar com Syth desta vez. O Syth definitivamente está entrando em guerra aqui. Pode ser OP, na verdade. Ok, então Syth quatro, vamos ver como isso funciona. Definitivamente, é muito difícil. Isso é muito importante. Como é basicamente um AOE, provavelmente não deveria estar causando tantos danos, sejamos honestos Ok, acho que já vi o suficiente lá. Vou apenas polir a lança. E torne a lança mais divertida de realmente usar. Então, vamos atacar o jogador, a arma de lança. Vamos entrar na definição da cena. que podemos melhorá-lo Acho que podemos melhorá-lo o quanto quisermos Nível um curto. Podemos deixar isso como padrão Nível dois, três, quatro, cinco. Vamos ver. Para o nível dois, vou fazer com que cause 20 a 30 de dano e esfrie. Sim, podemos fazer 0,9. O nível três será de 30 a 35. Acho que a lança também pode dar dois golpes no nível dois. Tudo bem. E, no nível três, causaremos 30 ou 40 de dano. Ok, então o máximo atinge dois, e então aumentaremos os projéteis para dois no nível quatro, e isso causará 35 a 45 de dano com 0,8 de resfriamento E então vamos causar 40 a 45 de dano. Pode ser mais rápido. Vamos fazer com que o resfriamento seja 0,6. Os projéteis podem ser, por que não? Digamos que três projéteis. Isso parece muito maluco, mas ei. E então eu vou fazer uma corrida rápida com a lança. Vamos ver se a lança pode até mesmo competir com a foice. Ok, mais lanças. Isso deve nos dar dois projéteis. Isso deveria ser muito melhor. Chegar ao nível quatro foi um pouco difícil. Não vou equilibrar muito isso, mas queria que fosse pelo menos suportável Oh, Deus. A desova está ficando meio ridícula. Oh, eu esqueci de repetir a música. Ok, abra o mundo do jogo. Isso é muito importante. Então, mundo do jogo. Vamos abrir essa cena. Temos o reprodutor de streaming de áudio. Queremos pegar essa música e dar uma olhada. Então, acho que precisamos fazer isso no projeto. Vamos fazer três. Clique duas vezes nele e ative o loop Tudo bem. Fechar. E depois reprodução automática Então, em seu reprodutor de streaming de áudio, vamos verificar Looping on para esse Isso também deve estar na tela do menu principal, por precaução. Então, aqui estão os parâmetros, continuo repetindo, e depois vou retomar o jogo Então, isso não vai começar até voltarmos lá. Então, como atingimos a lança de nível cinco, não podemos mais selecionar a lança É bom verificar novamente e garantir que, você sabe, não se preocupe ao tentar subir de nível até o nível seis Então, ainda podemos escolher a foice, é claro. OK. E eu vou me deixar morrer neste momento. Eu acho que sim. Tudo parece muito bem. Ah, e a tela de maior pontuação aqui, se ainda não estiver sendo exibida corretamente, vamos entrar nela. Então, para obter as pontuações mais altas, para garantir que haja espaço suficiente aqui, vamos definir um tamanho mínimo para elas. Vou definir isso para 60,0 e, em seguida, vamos expandir a base de pontuação máxima para a esquerda Ok, pegue também a etiqueta da quantidade, e vamos fazer um tamanho mínimo de 60, ok? E podemos pegar as pontuações mais altas e torná-las ainda maiores à esquerda. Tudo bem. E então aperte play. E certifique-se de que as pontuações mais altas não ultrapassem o limite em nenhum lugar. Então, isso seria bom para pelo menos mais um dígito, eu acho, sem ultrapassar a borda e embrulhar nem Ok, então, neste momento, praticamente, acho que o protótipo está relativamente polido Tenho certeza de que podemos fazer ajustes no código e no conteúdo a serem adicionados ao jogo e torná-lo um jogo completo Mas no que diz respeito ao curso, mostrando o básico de como configurar tudo isso, um sobrevivente como o jogo e o GD Script Gudo 4.4, acho que isso é praticamente tudo o que há Então, espero que tenham gostado acompanhar Long até o fim. Pode haver alguns pequenos vídeos de atualização, mas é só isso. Então, obrigado novamente por assistir Iben Chris, e vejo vocês no meu futuro conteúdo de vídeo