de UE5 para iniciantes: crie um Shoot 'Em Up do zero. | Dev Enabled | Skillshare

Velocidade de reprodução


1.0x


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

de UE5 para iniciantes: crie um Shoot 'Em Up do zero.

teacher avatar Dev Enabled

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.

      00

      1:47

    • 2.

      01 — Configuração

      9:24

    • 3.

      02 — PlayerPawn

      7:24

    • 4.

      03 — estrutura de jogo

      10:56

    • 5.

      04 — LegacyInput

      8:23

    • 6.

      05 — PlayerMovement

      10:58

    • 7.

      06 — suavidade em movimento

      18:33

    • 8.

      07 — Input aprimorado

      10:22

    • 9.

      08 — Limites

      13:16

    • 10.

      09 — Instâncias de materiais

      13:16

    • 11.

      10 — EnemyMovement

      14:41

    • 12.

      11 — EnemyCollision

      12:31

    • 13.

      12 — Base Class de herança herança

      9:59

    • 14.

      13 — RefactoringPlayer

      10:33

    • 15.

      14 — Refatoração do inimigo

      7:49

    • 16.

      15 — Sistema de saúde

      12:35

    • 17.

      16 — Movimento Melhorado

      14:08

    • 18.

      17 — Rotação melhorada

      13:04

    • 19.

      18 — EnemySpawner

      15:16

    • 20.

      19 — ProjectileBase

      22:13

    • 21.

      20 — Projeto: fogo do inimigo

      13:30

    • 22.

      21 — ProjectileFire Player

      7:07

    • 23.

      22 - RolagemFundos Fundo

      18:23

    • 24.

      23 — NiagaraParticles

      13:34

    • 25.

      24 — Efeitos de áudio

      10:08

    • 26.

      25 — SpawnAnimations

      23:57

    • 27.

      26 — CameraShakeKnockback

      18:56

    • 28.

      27 — UI

      16:54

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

7

Estudantes

--

Sobre este curso

Visão geral do curso

Crie um jogo shoot 'em up completo no Unreal Engine 5 usando blueprints. Vá do código zero para um jogo totalmente jogável com movimento do jogador, inimigos, projéteis, efeitos de partículas, áudio, interface do usuário e um loop de jogo de trabalho. Esta série de 27 tópicos se concentra nas melhores práticas de programação, arquitetura de projetos limpa e entender por que as coisas funcionam, e não apenas clicar nas etapas.

Cada sistema é construído corretamente: movimento independente da taxa de quadros, hierarquias de classes baseadas em herança, arquitetura spawner reutilizável e design orientado por componentes. Você vai escrever o mesmo tipo de código que escreveria em um projeto de verdade. Sem atalhos que se desfaçam no instante em que você tenta estendê-los.

O que você vai aprender

  • Configuração e organização do projeto dimensionada (estrutura de pastas, convenções de nomenclatura, configurações do projeto) Compartil
  • Movimento do jogador e do inimigo com independência de taxa de quadros usando o Delta Time
  • Sistema de entrada aprimorado — o framework de entrada moderno do Unreal
  • Detecção de colisão e eventos de sobreposição
  • Herança e refatoração: como criar uma classe base compartilhada e, em seguida, converter os blueprints existentes para usá-la para
  • Um sistema de saúde e danos que funciona para qualquer ator
  • Arquitetura do Spawner com temporização e posicionamento randomizados (reutilizado para inimigos e fundos)
  • Sistemas de projéteis personalizados — por que ignoramos o componente de movimento de projéteis integrado e construímos algo melhor
  • Materiais e instâncias de materiais: compreensão de materiais principais, canais de textura e criação de variações de cores
  • Rolagem de fundos com profundidade de estilo paralaxe
  • Efeitos de partículas do Niágara (propulsores, explosões, impactos)
  • Integração de áudio e toque de jogo
  • Criar animações usando linhas do tempo e curvas
  • Tremulação e retorno da câmera
  • Criação de UI com blueprints de widget, incluindo um loop de jogo completo (jogue → morra → reinicie ou sair) pincel

Por que você deveria fazer este curso

A maioria dos tutoriais do Unreal Engine mostra no que clicar. Este artigo explica o porquê. Todas as decisões. Desde a escolha de eventos de sobreposição em vez de bloquear colisões até a construção de movimento personalizado em vez de usar componentes integrados. Tudo é explicado para que você entenda a diferença e não apenas o resultado.

A série é estruturada para que cada vídeo se baseie diretamente no último. Os conceitos introduzidos cedo (como independência de taxa de quadros e hierarquias de componentes) reaparecem ao longo do curso, reforçando-os através do uso prático em vez da simples repetição. No final, você terá criado um jogo completo e extensível. Mais importante, você vai entender a arquitetura bem o suficiente para modificá-la, expandi-la ou aplicar os mesmos padrões a um projeto completamente diferente.

Não é necessário ter experiência anterior no Unreal Engine, mas a familiaridade básica com a interface do editor é útil. Se você abriu o Unreal e se sentiu perdido sobre por onde começar a criar algo de verdade, esse é o ponto de partida.

Conheça seu professor

Teacher Profile Image

Dev Enabled

Professor
Level: Beginner

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. 00: Isso é o que você construirá uma filmagem completa no Unreal Engine Five, inteiramente em um projeto Eu sou Rob e, ao longo desses 27 tópicos, esta série levará você de uma base de código vazia a um jogo jogável finalizado Criaremos nosso próprio movimento de jogador totalmente personalizado com independência da taxa de quadros, usando o sistema de entrada aprimorado e abordando detalhadamente coisas como detecção de colisões Vamos implementar as classes de peões para os inimigos e os aviões dos jogadores com foco na herança, então uma classe base, que alimenta cada tipo de navio, adicionando um sistema de projéteis que funcionará para ambos os lados, uma única classe, que Até mesmo as classes de desova que criamos são configuradas com uma arquitetura que lidará com inimigos e planos de fundo, e você pode estendê-la como quiser Também daremos uma pequena olhada em coisas como design e aprimoraremos o jogo com efeitos de partículas , áudio, trepidação da câmera e até mesmo Adicionaremos um loop de jogo completo, para que você tenha um jogo jogável até o final, incluindo sua interface de usuário Você pode jogar, morrer, reiniciar ou sair. O foco será fazer as coisas corretamente. Vamos analisar arquitetura limpa, sistemas reutilizáveis e realmente entender por que algo funciona ou não, e realmente entender por que algo em vez de apenas copiar as notas Cada decisão é explicada. Eu pularei propositalmente recursos integrados do Unreal e, em seguida, explicarei por que tomamos Quando algo é contra-intuitivo, eu chamo a atenção e todos os recursos que você precisa acompanhar e obter os resultados finais são fornecidos, que significa que você pode se concentrar apenas na programação e na uma boa estrutura de projeto todos os recursos que você precisa acompanhar e obter os resultados finais são fornecidos, o que significa que você pode se concentrar apenas na programação e na criação de uma boa estrutura de projeto. Eu cuidei da arte para você Seu projeto de classe será esse jogo finalizado, totalmente polido, aprimorado e pronto para ser expandido em uma peça de portfólio, junto com quaisquer novos recursos que você decidir adicionar Pode haver novos inimigos, armas, um sistema de pontuação, o que você quiser A arquitetura será definida de forma que você possa construir e ampliar. Por exemplo, considerei o projeto mais ou menos assim em alguns meses e adicionei vários novos recursos e ativos a um projeto estendido. O primeiro vídeo abordará a configuração do projeto. Estou ansioso para ver você lá. 2. 01 — Configuração: A maioria dos projetos irreais se torna impossível de navegar em um mês. Os ativos ficarão espalhados por toda parte, sem convenções de nomenclatura, e você acabará passando a maior parte do tempo pesquisando em vez de tempo pesquisando em vez Eu criei esta série com a intenção de corrigir isso desde o início. Ajudarei você a criar uma filmagem completa do zero, que cada tópico se concentrará em fazer as coisas corretamente. Essa é uma boa estrutura, boa nomenclatura, boa arquitetura, habilidades que serão transferidas para qualquer projeto em que você trabalhe Trabalharemos para criar o jogo que você pode ver em segundo plano aqui com base no conteúdo oficial criado pela Epic em seu pacote de exemplos de conteúdo. Se isso é algo que desperta seu interesse, então vamos começar e criar essa base Primeiro, eu recomendo que você navegue até o link de download na descrição. Você verá duas opções aqui. Nós os aprimoramos em ativos sublinhados Ele contém as malhas e texturas de regras, caso você queira modificar alguma coisa no Blender ou no Photoshop Em seguida, você tem que atirar neles, iniciar o tutorial de sublinhado, e este é o projeto completo E esse será o que você deseja acompanhar junto com os tópicos que abordamos. Por padrão, isso será fornecido como uma pasta compactada para você Portanto, você precisa ter certeza de extrair isso em algum lugar sensato, e começar do mesmo projeto significa simplesmente que estamos trabalhando com configurações idênticas, os mesmos ativos, trabalhando na mesma escala e assim por diante, que tornará a solução de problemas um pouco mais fácil se você tiver problemas A primeira coisa a ver dentro da pasta extraída é entrar na pasta do tutorial shoot them up underscore Por padrão, o projeto está no Unreal Engine 4.27 para máxima compatibilidade se você quiser trabalhar com uma versão de mecanismo um pouco mais antiga Se, como eu, você atualizará isso para funcionar com o Unreal Engine five A atualização leva cerca de 10 segundos. No Windows, você pode simplesmente clicar com o botão direito do mouse neste projeto dot U aqui e você tem a opção de selecionar a versão do Unreal Engine No menu suspenso, escolha a versão instalada com a qual você deseja trabalhar e clique em OK. Você está pronto para ir. Atualmente, estou trabalhando no Linux, então vou mostrar uma abordagem alternativa. De qualquer forma, isso é útil. Isso funcionará no Windows e, na verdade, é uma coisa muito útil de se saber, pois pode ajudá-lo a corrigir projetos que, de outra forma, não seriam abertos devido a problemas como plug-ins ausentes e problemas de plug-in. Então, para fazer isso, vou clicar com o botão direito do mouse no projeto dot U. Eu vou abrir o W, e você pode escolher qualquer editor de texto. Isso pode ser o código do Notepad VS. Vou trabalhar com Zed, e podemos ver aqui no lado esquerdo que, se olharmos para a associação Engine, ela está nos dizendo que isso foi feito com 4.27. Nós podemos simplesmente mudar isso. Vou trabalhar com o 5.6, que provavelmente está desatualizado no momento que você estiver assistindo, mas estará próximo o suficiente Feito isso, como em qualquer editor de texto, podemos simplesmente salvar isso. Podemos fechar a janela, e agora está pronto para começar. Para começar o projeto, basta clicar duas vezes no projeto dot U, e ele começará a ser carregado em segundo plano , ou seja, no Linux Clicar duas vezes em um projeto U por padrão não inicia o mecanismo Unreal Se você quiser esse tipo de integração com meu instalador personalizado do UnrelEngine, isso fará coisas como encontrar todas as versões baixadas ou instaladas localmente do Unreal, adicioná-las a um lançador automático aqui, e podemos simplesmente usar o Impress Okay, e podemos carregar o lançador bastante padrão que você normalmente obteria com o que você normalmente obteria Na verdade, não é o tópico principal do que vamos abordar, então fornecerei um link adicional para isso. Você pode verificar isso na descrição abaixo. Eu fornecerei os scripts de forma totalmente gratuita, para que você também possa baixá-los. E isso será mais aprofundado do que o que eu precisava fazer para colocar o Linux em funcionamento, pronto e funcionando perfeitamente com o motor UnRel Agora que estamos dentro do Unreal, sua interface pode parecer um pouco diferente da minha , dependendo da versão com a qual você decidiu trabalhar A Epic tende a reorganizar as coisas aproximadamente toda vez que alguém fica um pouco entediado Mas podemos nos concentrar apenas nos conceitos, não nos botões e nos locais exatos. Eles definitivamente existirão e você estará pronto e funcionando com rapidez suficiente. A primeira coisa a verificar é o navegador de conteúdo ou a gaveta de conteúdo, que está no canto inferior esquerdo É aqui que reside tudo em seu projeto. Podemos clicar aqui e ver a estrutura do nosso projeto. Dentro da pasta de conteúdo, há uma subpasta que corresponde ao nome do projeto, que é o tutorial Shoot them up underscore, e essa é a convenção de nomenclatura recomendada pela Epic para projetos e estruturas Dentro disso, temos uma pasta de ativos que contém coisas como nossas malhas, texturas e Temos uma pasta de diagramas para nosso código e lógica, e temos uma pasta de mapas para nossos níveis Essa é uma estrutura simples, mas pode ser dimensionada para qualquer tamanho de projeto. A outra coisa que você pode notar navegar por algumas das pastas são coisas como as convenções de nomenclatura que foram escolhidas Temos coisas como MM underscore texture, que significa material mestre Em seguida, temos o sublinhado MI, seja qual for a finalidade do material, e essa é uma instância material Se usarmos as texturas, teremos coisas como nosso herói de avião T underscore, que é T para Acho que o lugar de onde todas essas convenções de nomenclatura não são aleatórias Tudo isso é baseado no estilo AA. Se quiser pesquisar isso no Google, você pode encontrar isso aqui, então podemos simplesmente pesquisar o Guia de Estilo e estamos procurando a página do Github, a primeira aqui Um link para isso também estará na descrição abaixo. Nomear coisas é supostamente um dos problemas mais difíceis da ciência da computação, e isso resolve um desses Eu recomendaria marcar isso como referência. E então, sempre que você estiver criando um novo tipo de ativo, se não tiver certeza de como chamá-lo, verifique aqui e, por meio da repetição, isso se tornará automatizado No entanto, é um recurso muito bom. Ele fornece praticamente tudo o que você poderia desejar. Você não precisa se lembrar de tudo de uma vez. Há muitas coisas aqui. Mas se analisarmos as convenções gerais de nomenclatura, temos coisas como malhas esqueléticas, que seriam O material para Bob seria M nscore Bob, textura para Bob seria T underscore Bob e assim por diante Se você observar as plantas, temos coisas como o sublinhado do BP e, em seguida, também podemos verificar coisas como a estrutura de arquivos e pastas Então, exatamente como mencionei aqui, o nome do projeto e, em seguida, todas as pastas em uma configuração um tanto lógica e significativa. Então, essa é realmente a essência de como estruturar seus projetos, como manter as coisas arrumadas e como se organizar à medida que avança Para começar, precisamos de um nível principal para trabalhar com ele. Antes de me aprofundar nisso, quero fazer algo e apresentar a você apenas para facilitar a visualização da minha tela, mas isso também pode ser útil para você conhecer. Então, vou até as configurações de edição aqui na parte superior da tela e vou para as preferências do editor. É aqui que podemos alterar diferentes recursos sobre como o editor é apresentado, os atalhos, as combinações de teclas e coisas assim podem ser encontradas O que eu quero mudar é a escala do aplicativo aqui. Vou apenas mudar isso para 1,25. Isso ocorre simplesmente porque eu tenho uma tela bem grande configurada, então ela pode parecer um pouco esticada e os botões podem parecer um pouco pequenos para você acompanhar Então, como eu disse, isso é opcional, mas é útil saber que isso existe. E há muitas outras coisas que você pode fazer dentro das preferências do editor para ajustar a aparência geral do seu editor, caso algo não esteja certo para você trabalhar No entanto, isso salva automaticamente, então vou fechar a janela e agora podemos começar a criar nosso primeiro nível. Isso é bom e simples. Podemos ir para o lado superior esquerdo. Temos nosso botão de arquivo e temos a opção aqui de criar um novo nível. Uma coisa a observar são os atalhos. Podemos ver todas as teclas de atalho. Novos níveis são algo com que costumamos jogar bastante. Portanto, talvez valha a pena lembrar desde o início para economizar um pouco de tempo Dentro da nova janela, vamos selecionar apenas o nível básico, não o mundo aberto. Isso vai ser muito complexo para o que precisamos agora. E também leva mais tempo para carregar no editor toda vez que você inicia o backup. Então, clicaremos duas vezes em Básico e agora estamos dentro do nosso novo nível básico. Então, vamos nos certificar de que também salvamos isso corretamente. Por padrão, isso é chamado de Sem título, o que significa que ainda não o salvamos. Isso não está armazenado. Se fecharmos o projeto e voltarmos , perderemos nosso progresso. Então, vamos pressionar Control em S dentro da janela de visualização aqui, Controlando S para salvar Vamos descer até a pasta do tutorial do Shootm up, ir até a pasta Maps e chamá-la de principal Podemos dar o nome aqui embaixo. Pressione Salvar ou Enter, e isso será salvo automaticamente. Dentro da gaveta de conteúdo, podemos acessar nossa pasta Mapas e ver que nosso mapa está aqui Uma coisa rápida de se observar. UnRel usa o mapa de palavras e o nível de forma intercambiável A mesma coisa, dois nomes diferentes , porque é claro que sim. Podemos ver que aqui, na verdade, isso é chamado de nível, mas quando usarmos isso posteriormente, Unreal solicitará que definamos um mapa específico Outra coisa a ser observada e com a qual trabalharemos com bastante frequência é a gaveta de conteúdo Então, em vez de pressionar constantemente o botão aqui no canto inferior esquerdo, podemos pressionar Control no espaço, e isso fará com que a gaveta de conteúdo se abra e feche constantemente o botão aqui no canto inferior esquerdo, podemos pressionar Control no espaço, e isso fará com que a gaveta de conteúdo se abra e feche E essa parte é muito importante. É aqui que os iniciantes sempre perdem o trabalho, ou pelo menos acham que sim, até voltarem e buscarem ajuda. Sem essa etapa, você fechará seu projeto, o reabrirá e se verá olhando para um mapa-múndi vazio aberto ou algo que não esperava Seu rótulo principal ainda existe, mas o Unreal não sabe que deveria ser aberto por padrão Então, para mudar esse comportamento, vamos para as configurações do projeto. Vamos editar e depois as configurações do projeto. No lado esquerdo, na categoria superior, queremos encontrar a opção de mapas e modos. E então, no lado direito, você vê o mapa de inicialização do editor. Altere essa lista suspensa do modelo padrão para nosso mapa principal que acabamos de criar, e isso informa ao mecanismo Unrel qual nível abrir quando você inicia o projeto pela primeira vez Também podemos definir o mapa padrão do jogo aqui como principal. Isso determina o que o jogador vê se você realmente empacotar o jogo e entregá-lo a outra pessoa para jogar. Todas essas configurações são salvas automaticamente, para que possamos fechá-las. Podemos reabrir o projeto, e isso significa que você retornará exatamente onde parou, desde que tenha a chance de salvar o mapa em que está trabalhando Portanto, isso pode parecer muito trabalho extra e muita conversa apenas para o primeiro tópico. Mas esses fundamentos realmente se compõem. Um projeto organizado permanecerá gerenciável em 10 horas de trabalho, 100 horas e até 1.000 horas, enquanto um projeto confuso simplesmente não E esse é realmente o objetivo e o foco de toda essa abordagem baseada em projetos. As coisas podem demorar um pouco mais, mas, no final, você entenderá o que está fazendo e com sorte, eliminará algumas boas práticas e tornará seus projetos futuros muito mais intuitivos e fáceis de trabalhar Mas com isso dito, as bases estão bem definidas. A estrutura do projeto, a convenção de nomenclatura e as configurações estão todas configuradas corretamente. O próximo tópico será criar nosso peão de jogador, que é algo que você pode realmente controlar E, como já mencionei, quero que você realmente aprenda o que está fazendo à medida que avança Uma das melhores maneiras de aprender não é seguir o passo a passo. Quando você sentir que entendeu alguma coisa, tente ampliá-la Mesmo para algo tão simples quanto fizemos agora, adicione suas próprias pastas, renomeie algumas coisas e prove para si mesmo que você entende o padrão, não apenas as etapas vou orientá-lo sobre isso durante todo De qualquer forma, vou orientá-lo sobre isso durante todo o curso do que estamos fazendo, mas não há muito que eu possa fazer, e muito do trabalho virá do autoaprendizado Se você fizer alterações que funcionem bem, coloque-as nos comentários e discussões abaixo. E se você acha que entendeu alguma coisa e vê alguém postando uma pergunta que você acha que pode responder, tente responder Explicar algo que você acabou de aprender é uma das maneiras mais rápidas e melhores realmente bloquear as novas informações e garantir que você não as esqueça no futuro 3. 02 — PlayerPawn: Os projetos agora estão configurados e precisamos de algo para realmente começar a controlar. No final deste tópico, teremos um peão de jogador com vigílias. Ainda não vai se mover. Isso virá a seguir, mas entenderemos exatamente como e por que o Unreal decide gerar coisas e onde Uma das principais coisas no desenvolvimento é planejar com antecedência e realmente pensar sobre qual é sua meta atual e como alcançá-la. Então, simplesmente, pelos vídeos, sabemos que queremos controlar esse pequeno personagem em um pequeno avião azul, para garantir que ninguém fique para trás. Se você é completamente novo em tudo, não quero usar jargões completos. Então, vou mostrar algumas coisas realmente básicas. O plano que estamos vendo é algo chamado malha estática. Então, se formos para as malhas de ativos, podemos ver aqui que essa é uma malha estática do nosso pequeno personagem no plano azul Então, queremos controlar isso. Se colocarmos isso diretamente no nível, não conseguiríamos controlar uma malha estática Precisamos fazer esse código baseado em código e usar um tipo de classe de blueprint no mínimo, para fazer isso funcionar Dentro do Unreal, isso é chamado de peão, algo que podemos possuir ou controlar, essencialmente, apenas um tipo especial de ator Então, vamos criar nosso peão corretamente com nossa boa estrutura de pastas Então, vou entrar em nossa pasta Blueprints. Dentro daqui, queremos criar uma nova pasta. Podemos clicar com o botão direito do mouse e pesquisar a nova opção de pasta aqui. Costumo usar o atalho Control Shift e N para criar uma nova pasta lá. Então N para novo. Vou renomear essa pasta para CR. Essa será nossa principal mecânica de jogo ou recursos de jogo E então, dentro dessa grande estrutura de pastas, se clicarmos com o botão direito do mouse, queremos ir até a opção de classe de blueprint aqui, e isso nos permitirá criar um novo blueprint, e podemos ver uma variedade de opções diferentes E é aqui que entender a hierarquia de classes da Unreal pode começar a ajudar Resumindo, tudo dentro do UnRel herda de algo chamado objeto Esse é apenas um contêiner de dados, a classe mais simplificada à qual temos acesso. Muitas vezes, então, vemos algo chamado ator. Tudo no nível no momento está na raiz de uma classe de ator. Teremos atores de malha estática, atores de câmera, atores leves, mas todos eles são atores em sua raiz. Adiciona uma presença física sobre os dados do objeto, que é uma localização, rotação e escala chamadas de transformação. E então, os peões com os quais trabalharemos são apenas um ator com a funcionalidade necessária. Você verá em alguns tutoriais que, em vez disso, eles usarão algo chamado classe de personagem, e isso seria um exagero para o que pretendemos fazer com essa filmagem Os personagens incluem coisas como mecânica de caminhada, gravidade, colisão de cápsulas, coisas realmente projetadas para personagens humanóides andando a pé Vamos fazer uma nave espacial, então realmente não precisamos de nada E isso vem com muitas despesas extras que precisaríamos para trabalhar ativamente Então, você pode ver outros tutoriais criando coisas como um controlador de tanque usando uma classe de personagem, e é aqui que estar ciente de coisas assim permitiria que você considerasse que essa pode não ser a melhor solução para o que você está tentando Como os peões são um ator ou tipo de classe muito usado , podemos ver que isso está aqui na seção comum, então podemos clicar aqui e isso criará uma nova classe de peões para E queremos chamar isso de base de peões de sublinhado de BP, porque essa será a classe base para qualquer classe relacionada a peões que criarmos no futuro, permitindo também reutilizar parte da lógica de nossos inimigos, nomeando-a pelo que ela é em geral, não apenas pelo que ela deveria fazer antes de tudo, que funcionará como nomeando-a pelo que ela é em geral, não apenas pelo que ela deveria fazer antes de tudo, classe de jogador Antes de prosseguirmos, outra solução rápida à parte, rápida e de qualidade de vida. UnrelEngine tem algumas opiniões fortes sobre o gerenciamento de janelas e, na maioria das vezes, elas estão erradas Então, para corrigir uma das coisas que estão prestes a acontecer, se clicarmos duas vezes para abrir nossa planta agora, isso criará uma janela flutuante praticamente em qualquer lugar da tela Isso pode ser muito chato. Isso significa que o Windows pode se perder atrás de outros aplicativos e coisas assim. Então, se voltarmos para editar e depois para as preferências do editor. Mesmo lugar que mostrei anteriormente, onde mudei a escala do aplicativo. Como mencionei, podemos fazer muitas correções e mudanças na qualidade de vida. Eu quero descobrir que está no local aberto do editor de ativos. Queremos mudar isso do padrão, que está aberto em qualquer lugar, e vamos mudar isso para a janela principal. Você pode experimentar coisas diferentes e ver o que pode funcionar melhor para você. Eu gosto bastante da janela principal. É como trabalhar em um navegador da web, então, onde cada novo arquivo, planta, ativo, seja o que for com o qual você está trabalhando Sempre que você abre uma nova janela, ela cria uma nova guia e a encaixa como marcadores na parte superior Então, novamente, isso é salvo automaticamente, podemos fechá-lo, voltar para a gaveta de conteúdo e clicar duas vezes novamente para abrir a base da panela Você pode ver que isso se abre aqui, que é exatamente o que eu queria. Se você fez o mesmo que eu, onde você pode ter aberto isso duas vezes, você pode ser recebido com essa visualização simplificada somente de dados E isso está perfeitamente bem. Não precisamos entrar em pânico. Esses são todos os detalhes da aula apresentados a nós essencialmente em texto ou em formato suspenso. Para voltar ao editor de plantas completo, queremos apenas essa linha azul de textura, o editor de quatro plantas abertas, e isso nos levará de volta para onde queremos estar Ok, então há muitas informações que eu poderia fornecer agora, mas você provavelmente esqueceria a maior parte delas. Então, vamos adotar uma forma mais orgânica e natural de aprender o motor irreal Vamos apenas trabalhar com novos recursos, e eu os apresentarei à medida que avançarmos e à medida que se tornarem relevantes. A primeira coisa que podemos ver no momento é que estamos no gráfico de eventos nesta guia aqui. É aqui que colocamos nossa lógica e código. Nós vamos voltar aqui mais tarde. Por enquanto, se clicarmos no ponto de vista, é algo semelhante em que podemos dar uma olhada e ver como será a aparência de nossa classe de blueprint As classes de blueprint normalmente são compostas por componentes diferentes, cada um com seus próprios recursos e funcionalidades No lado esquerdo, podemos ver o painel de componentes e queremos adicionar nossa representação visual , essa malha estática. Então, se pressionarmos ad e pesquisarmos por malha estática, podemos ver isso aqui. Essa será a primeira parte do quebra-cabeça que estamos tentando resolver. Com a malha estática selecionada, no lado direito da janela, podemos ver nosso painel de detalhes. Isso nos diz tudo sobre o componente que selecionamos atualmente. Podemos ver que temos uma lista suspensa aqui para a malha estática, e essa é a representação visual que queremos definir. Sabemos que queremos que esse seja o avião azul, então encontraremos o herói do avião e selecionaremos aquele. Dentro desse visor, estou apenas usando a roda do mouse para rolar para dentro e para fora. Se pressionarmos Alt e clicarmos com o botão esquerdo, podemos arrastar e ver o modelo, e se pressionarmos o botão direito do mouse e arrastarmos o mouse, podemos mudar o que estamos vendo. Clique com o botão do meio do mouse e mova Will Dolly ou Pan, acho que está chamando E esse é o básico para navegar por esse visor e também pela janela de navegar por esse visor e também pela visão mundial mais tarde, quando chegarmos à construção de níveis e Outra coisa que é útil saber é que se você pressionar F quando tiver algo selecionado, você se concentra. Então isso é F para foco. Agora, o que acabamos de criar é nossa malha estática, e podemos ver no painel de componentes que temos algo chamado raiz de cena padrão. Isso mostra a estrutura do ator, e todo ator precisa de pelo menos uma raiz de cena padrão, um ponto no espaço onde todo o resto esteja conectado. A raiz de cena padrão que temos é apenas um espaço reservado, para que possamos pegar nossa malha estática e arrastá-la até a raiz da cena padrão e soltá-la raiz da cena padrão e soltá-la Então, perna esquerda e agora criamos nossa malha estática, o que é chamado de componente raiz, ou seja, o elemento básico de nossa classe de jogador ou nosso peão Outra coisa: quando chegamos a um estágio que achamos que estamos muito satisfeitos com o progresso, precisamos ter certeza de que adquirimos o bom hábito de clicar em compilar e salvar Isso apenas garante que, se alguma coisa falhar, não percamos nosso trabalho E, ao compilar, apenas verificamos se há erros e detectamos os erros mais cedo Então, agora temos nosso peão com imagens. Mas é claro que , se pressionarmos play, ainda não veremos isso porque ainda não dissemos ao Unreal Engine que o usasse E podemos usar algumas entradas padrão de jogo em primeira pessoa aqui. Então, WAS e D levarão você por aí. Q e E o moverão para cima e para baixo e, claro, o mouse olhará ao redor. Mas, é claro, essa não é exatamente a funcionalidade que estamos procurando. Então, no próximo tópico, corrigiremos isso examinando a estrutura de jogabilidade do Unreal Engine Diremos ao motor Unreal exatamente o que gerar e onde queremos que ele apareça Mais uma vez, se você estiver experimentando sozinho, o que eu sempre recomendo, tente adicionar outros componentes à classe peão Algo tão simples quanto uma luz pontual, um sistema de partículas padrão, só para ver o que acontece quando você anexa coisas a diferentes partes da hierarquia Esse tipo de experimentação é, na verdade, como você fará com que essas coisas grudem 4. 03 — estrutura de jogo: Com o peão construído, pressionamos play e já vimos que, no modo de jogo, acabamos voando em torno do que é chamado peão padrão. Então, precisamos mudar isso. Unreal spawns vem por padrão e ignorou completamente a classe que criamos Para corrigir isso corretamente, precisamos realmente entender como a estrutura de jogo da Unreal decide o que gerar, onde, e então podemos dizer a ela o que fazer em vez disso Então, para começar, uma pequena visão geral do conceito, mais uma vez, deixe-me mostrar o que realmente está acontecendo nos bastidores. Em primeiro lugar, vou voltar para a janela principal e pressionar play. Dentro do Playode, é aqui que podemos voar. Algo que é realmente útil saber é que você pode pressionar F oito para ejetar do jogo Então, eu ainda estou no modo de jogo. Mas eu não estou mais controlando a pornografia padrão. Agora estou basicamente de volta ao modo editor para poder usar WAS e D, clicar com o botão esquerdo do mouse para dar uma olhada e ver o que está acontecendo durante o jogo. Se olharmos para o contorno no lado direito, podemos ver algo chamado pornografia padrão zero Isso é o que realmente estamos controlando no nível. E, de fato, tudo destacado em amarelo aqui foi gerado pela estrutura de jogabilidade UnrelEngine Não colocamos nenhum desses no nível. Então, quando pressionamos Play, o UnRel segue uma cadeia específica. Primeiro, ele verificará um modo de jogo e, se você não tiver definido um , usará uma opção padrão. O modo de jogo então decidirá qual peão gerar. E, novamente, se você não especificou um, ele usa o padrão, que é literalmente chamado de peão padrão E isso é atualmente o que estamos controlando em vez de nosso avião, porque nunca dissemos à Unreal que usasse essa classe de avião Então, vamos pressionar Escape para sair do Modo Play e podemos começar a assumir o controle do nosso projeto. De volta à pasta principal. Então, se você não está realmente aqui, os blueprints estão dentro da gaveta de conteúdo, queremos criar uma nova classe Blueprint Da mesma forma que antes, clique com o botão direito do mouse e vá para a classe Blueprint E desta vez, queremos criar uma base de modo de jogo única. Vou dar a este o nome de base do BP Underscore Game Mode. E um modo de jogo é essencialmente algo que podemos considerar como um detentor de regras. Ele diz ao NRLEngine quais classes usar para tudo, qual pan gerar, qual controlador usar, qual Hud exibir Se clicarmos duas vezes para abrir nosso modo de jogo, podemos ver que isso parece um projeto normal Poderíamos entrar na seção Gráfico de eventos de código se quiséssemos, mas tudo o que queremos está, na verdade , no lado direito do painel de detalhes. Podemos ver aqui as coisas que acabei de mencionar, o tipo de controlador Hud padrão , está tudo exposto aqui O que estamos procurando é nossa aula de pornografia padrão aqui. Podemos derrubar isso e mudar isso para a base pornográfica do BP Underscore Isso é praticamente tudo o que precisamos fazer aqui. Podemos clicar em Compilar e salvar para garantir que tudo isso seja atualizado E podemos realmente sair do modo de jogo por enquanto. Vou manter isso aberto para dar um pequeno exemplo visual de algo em apenas um momento, mas isso é praticamente tudo o que precisamos fazer dentro do nosso modo de jogo. Como era de se esperar, apenas criar o modo de jogo não é suficiente. Agora precisamos dizer ao projeto que realmente faça uso dele. Então, se voltarmos para a opção de edição no canto superior esquerdo, iremos para as configurações do projeto novamente. E, na verdade, estamos relembrando onde estávamos anteriormente, na seção de mapas e modos. Você pode ver no lado direito, temos o modo de jogo padrão chamado base do Modo de Jogo. E se deixarmos isso aqui, podemos realmente ver o que ele estava usando. Então, estava usando uma classe Hod padrão, a classe de peão padrão, a coisa que literalmente nos vimos voando, o controlador do jogador por padrão e assim por diante Não podemos alterá-los, e é por isso que precisávamos de uma classe personalizada para trabalhar. Se derrubarmos essa opção, podemos alterá-la para a base do Modo de Jogo com sublinhado BP Podemos ver que isso agora está liberado. E o importante é que agora mudou essa para ser nossa base de peões de sublinhados da BP A única coisa que eu queria te mostrar rapidamente é que, se eu mudar isso aqui, eu poderia descartar este. Vou mudar isso para algo completamente único. Mudamos isso para o personagem Arc Vz. Na verdade, podemos ver que a classe do modo de jogo que criamos em segundo plano, então nossa base do modo de jogo BP Underscore foi atualizada em segundo plano para ser Arc Vz Se clicarmos aqui e mudarmos esta volta para a base de peões de sublinhado da BP, eu só queria destacar que eles estão completamente Então, se mudarmos alguma coisa aqui, isso será atualizado em nossa classe Blueprint E se mudarmos alguma coisa em nossa classe Blueprint, isso mudará nas configurações do nosso projeto se a tivermos conectada aqui Feito isso, podemos fechar as configurações do projeto, certificar-se de compilar e salvar o modo de jogo Se você estiver brincando com coisas, volte para o nível principal, pressione play, que é O e P, o atalho para entrar no modo de jogo E estamos meio que no avião agora. Na verdade, estamos literalmente no avião. Então, outro problema para resolver, mas estamos chegando mais perto. Se você estava colocando as coisas manualmente mais cedo, se estiver brincando com coisas, você pode ter outros aviões no nível como. Certifique-se de se livrar deles apenas para que não haja confusão, mas podemos ver o que está acontecendo. Pressionamos play, entramos no modo play e, se eu pressionar F oito para pular de volta, você pode ver que agora ele realmente gerou um avião para controlarmos O principal problema é que estamos dentro dela. Eu só queria destacar outra coisa que está acontecendo com a estrutura de jogabilidade, que é o uso do nosso player start. Então você pode ver isso aqui mesmo no nível. E no esboço, podemos ver é chamado aqui de player Isso é o que a estrutura procurará para confirmar onde você deseja realmente gerar o peão que deseja controlar Então, se eu mover isso para algum lugar muito distante, eu movo isso até o espaço aberto aqui. Se eu pressionar play, ainda estamos gerando o avião, mas agora estamos surgindo ao ar Então, novamente, algo útil para saber. Se não tivermos um desses, podemos excluí-los, mas o Unreal agora precisa adivinhar onde queremos gerar nossa coisa E não é realmente uma suposição apenas para mostrar o que acontece com esse cenário Se eu me mover no visor, estou novamente usando o botão direito do mouse para olhar ao redor e depois W AS e D para voar com base em onde estou olhando Se eu pressionar play, podemos ver que o avião agora vai aparecer na última posição em que minha câmera estava no visor Então, novamente, algo que acabei de ver novos desenvolvedores porque pode não estar muito claro o que o jogador Start estava fazendo, especialmente se você estiver trabalhando em um projeto em que você pode ter algo como um personagem de terceira pessoa ou um personagem de primeira pessoa com gravidade, você trabalhará no nível, algumas coisas, pressionará play, e então você cairá repentinamente no espaço, evitando completamente o nível e ficará um pouco confuso. E isso é só porque você provavelmente se livrou da sua largada de jogador. Unreal não sabia onde gerar seu personagem padrão, então escolheu o último lugar em que você esteve no editor Se você acompanhou até aqui, podemos acessar o botão Adicionar na parte superior. Podemos procurar um jogador começando aqui mesmo, e podemos simplesmente colocar um deles de volta no nível. Calma e calma, estamos de volta onde estávamos. Então, isso só deixa um problema : estamos procurando no lugar errado. Isso significa apenas que precisamos de uma câmera e precisamos dizer ao Unreal qual usar Para fazer isso, precisamos voltar à pornográfica da BP underscore Se você realmente não tem isso aberto, lembre-se disso na gaveta de conteúdo, então controle o espaço e clique duas vezes na classe base pornográfica Como mencionei, a maioria das classes é composta apenas por várias quantidades de componentes, cada componente tentando preencher uma função ou caso de uso específico. Nesse caso, queremos que um componente de câmera veja nossa correspondência estática. Antes de adicionarmos uma câmera, vou adicionar algo chamado Spring Arm apenas para apresentá-las. Então, se pressionarmos o anúncio aqui, podemos pesquisar por Spring Farm. Clicaremos para adicionar isso. E isso é basicamente um bastão que manterá a câmera a uma distância fixa. Ele também pode lidar com coisas como colisão, empurrar a câmera para mais perto quando batemos em paredes e tentar evitar Não precisaremos desse nível de complexidade para nosso jogo, mas é útil saber que esses recursos existem. Outro uso muito útil do braço de mola é que ele evita que precisemos afetar diretamente o deslocamento, a posição e a rotação Então, vamos mantê-lo apenas por esses motivos. Com o braço de mola ainda selecionado, voltaremos ao botão Adicionar. Vamos procurar uma câmera. E queremos selecionar a câmera padrão aqui na parte superior. Você pode ver que isso é colocado apenas na câmera no final da primavera. Isso nos dá um pouco de tempo para focar no Unreal Engine e na maneira como ele trata a hierarquia Já vimos o fato de que a malha estática agora é classificada como a raiz da costura Portanto, onde quer que a raiz da costura vá, todo o resto segue, incluindo rotação, localização e escala A primavera é então classificada como filha da malha estática, e a câmera é filha da primavera Então, o que isso significa é que se eu pegar o componente spring um e depois mudar alguma coisa na rotação, por exemplo, eu sei que quero que a câmera olhe 90 graus para baixo na malha estática. Isso será -90 graus. Podemos ver que a câmera herda rotação que dei à mola. Eu faço a mola um pouco maior, então vou bloquear o local, e vou fazer com que seja do tamanho de dez, podemos ver que a câmera também fica dez vezes maior. Agora, não escalamos a câmera e a câmera dessa forma, mas eu só queria mostrar como a hierarquia funciona dentro do irreal com os componentes No entanto, queremos a rotação da câmera, então eu recomendo uma rotação de algo como -90, para que a câmera fique voltada diretamente para o player Se pressionarmos play, podemos ver como isso ficará. Então, talvez um pouco perto demais, pode ser um pouco difícil ver o que está acontecendo com os inimigos e os projéteis durante o jogo O zumbido da primavera tem outro recurso, que nos ajudará com isso É chamado de comprimento do braço alvo, e você pode ver isso novamente no painel de detalhes. Então, como mencionei, com a malha estática, quando temos algo selecionado, o painel de detalhes é apenas todas as informações sobre os componentes que você selecionou atualmente. O zumbido da primavera tem esse valor chamado comprimento do braço alvo, que é essa linha vermelha, e podemos definir isso para algo como 1.200, e isso seria aproximadamente onde queremos Assim, podemos pressionar Play e ver que podemos ver um pouco mais da tela. voltaremos e refinaremos qualquer forma, voltaremos e refinaremos coisas assim um pouco mais tarde Mas, por enquanto, tudo ficará perfeitamente bem. Mais uma vez, quando você fizer alterações com as quais está satisfeito, certifique-se de clicar em Salvar, e isso se parece um pouco mais com um jogo de tiro de cima para baixo Então, se você está acompanhando e prestando atenção, agora vimos que, se não dissermos ao motor Unreal qual mapa usar, ele usa um mapa um tanto aleatório Se não dissermos qual modo de jogo usar, ele usa um modo de jogo padrão. E se você não disser qual peão usar, ele usa um peão padrão Mas você provavelmente notou que não dissemos qual câmera usar, mas ela sabe usar a câmera que acabamos de adicionar. Então, isso meio que quebra regra que venho destacando Neste trabalho, porém, tudo ainda se resume ao comportamento da estrutura de jogo. Quando a estrutura possuir um peão pela primeira vez, ela examinará dentro dessa classe e verificará se há algum componente da câmera Estou simplificando isso um pouco, mas é essencialmente o processo que é realizado Se encontrar uma câmera, ela será usada por padrão. Se ele não encontrar uma câmera em sua hierarquia , ele criará uma câmera padrão, e a posição em que a coloca é zero, que, no nosso caso, está diretamente dentro da malha plana, é por isso que estávamos olhando para o interior do corpo Então, novamente, agora podemos ver por que estávamos olhando para o interior do avião e como substituímos isso para agora olhar para baixo no No entanto, o mesmo tipo de padrão de todo o resto. A estrutura tem seus processos padrão, e o importante é que agora estamos mais conscientes de que temos a opção de substituí-los ou conviver com eles. Feito isso, agora controlamos o que aparece, onde aparece e por qual câmera olhamos A estrutura está trabalhando para nós em vez de contra nós. E, novamente, você pode se surpreender com quantas pessoas acabam trabalhando contra a estrutura por um bom tempo. Outra coisa com a qual me familiarizei bastante quando os alunos simplesmente mergulham de cabeça nos projetos Quando eu puder ver o projeto, depois de trabalharem nele por um tempo , eles terão soluções alternativas para eles terão soluções alternativas para visualizar por meio de câmeras específicas forçando os peões a serem acionados em determinados pontos, basicamente separando a estrutura e combatendo-a em vez Sempre que possível, podemos usar muitos desses princípios básicos de estrutura e, na verdade, eles nos ajudam mais do que nos atrapalham Claro, ainda não temos movimento. Atualmente, temos apenas um peão sentado lá e uma câmera para olhar para ele Então essa seria a próxima coisa, adicionar movimento. Na verdade, vou mostrar a maneira errada de adicionar movimento primeiro , porque é o que você verá em muitos tutoriais diferentes Depois de vermos isso, mostrarei como resolver esses problemas, para que você saiba o que procurar. Se você quiser experimentar novamente, a pequena recomendação, embora ainda estejamos muito cedo nos tópicos, seria tentar ajustar a distância ou o ângulo da câmera, talvez opte por uma configuração um pouco diferente para o ângulo em que você está olhando para o avião Pode adicionar uma segunda câmera e ver o que acontece. Qual deles ele escolhe? E se você estiver fazendo coisas assim, comece a tentar descrever o que você está percebendo que a estrutura está fazendo, o que ela está fazendo e o que você não espera, ou o que você está entendendo sobre isso 5. 04 — LegacyInput: Antes que o jogador possa se mover, o Unreal precisa saber o que os jogadores estão pressionando Isso pode ser teclas do teclado, controles, gatilhos. Tudo isso flui pelo sistema de entrada. Unre pega essas ligações e as converte em valores de entrada, e lemos isso para Portanto, o primeiro passo será entender como esses valores realmente funcionam. Para começar, faremos isso por meio sistema de entrada antigo, que é meio antigo. Para encontrá-los, queremos voltar às configurações do nosso projeto. Então, vamos subir para editar e projetar as configurações. Vamos descer um pouco mais do que antes. E podemos ver aqui que temos a seção de entrada. Como mencionei, isso é meio antiquado, e há até mesmo um aviso aqui sobre o sistema de entrada legado sendo descontinuado. Isso é bom. Ainda é útil saber porque é provável que você encontre projetos que ainda usam isso. Muitos exemplos e projetos ainda estão usando esse sistema. Tenha dois tipos diferentes de entrada aqui. Temos nossos mapeamentos de ações, que são binários. Eles são pressionados ou não, perfeitos para coisas como atirar, interagir, pular e assim por diante. Em seguida, temos nossos mapeamentos de eixos, convertem a entrada do player em valores contínuos de ponto flutuante Perfeito para movimento. Então, por esse motivo, vamos adicionar um novo mapeamento de eixos aqui, e nomearemos esse movimento para a direita. Como temos esse valor de escala aqui que podemos alterar para as diferentes entradas que fornecemos, chamaremos isso de movimento para a direita Ele também controlará o movimento para a esquerda tornando a outra entrada um valor negativo. Nessa lista suspensa, podemos encontrar qualquer entrada que desejarmos. Pode ser o teclado, o mouse, o gamepad, seja qual for o caso Algo que eu não sabia por muitos anos quando estava usando o motor unrel é isso Na verdade, é um botão. Se clicarmos nele e pressionarmos a tecla D, por exemplo, isso rastreará a próxima entrada como D, e isso seria perfeito para mover para a direita. Se pressionarmos o botão de adição, podemos adicionar outra encadernação. Vou pressionar isso novamente e depois pressionar A, então agora temos nosso movimento para a esquerda. A única coisa que mencionei é que, por padrão, esse é um valor positivo. Se mudarmos isso para um valor negativo, menos um, isso permitirá que a entrada nos mova na direção esquerda Se você quiser vincular chaves diferentes à mesma associação de entrada, podemos simplesmente adicionar mais duas como exemplo Podemos adicionar um para a seta direita e outro para a seta esquerda. Novamente, quando estamos nos movendo para a esquerda, queremos apenas ter certeza de adicionar o valor negativo a esse. Sistema simples e flexível o suficiente para o que precisamos fazer agora. Como tudo antes, isso é salvo automaticamente para que possamos fechar as configurações do projeto, voltar para a gaveta de conteúdo, usar o controle no espaço novamente como uma recapitulação do atalho e voltar para a base do atalho e voltar para a Se você ainda estiver dentro do visor, vamos querer passar para a guia do gráfico de eventos agora Então, aquela que eu mencionei, é aqui que nossa lógica vai seguir, e é isso que faremos imediatamente Aqui, podemos ver alguns nós diferentes que já estão no gráfico, e eu estou clicando com o botão direito do mouse e arrastando para me mover Primeiro, podemos ver que temos nosso modo de início de jogo, e isso acontece apenas uma vez quando pressionamos Iniciar Abaixo, temos nossa marca de evento na parte inferior, e esse evento é acionado continuamente enquanto o jogo está em execução. Você pode ouvir pessoas dizerem coisas como evitamos usar o marcador de eventos a todo custo, mas isso simplifica um pouco Para funcionalidades como movimento, onde queremos que seja suave e responsivo, ou movimento de câmera, física, coisas assim, é exatamente aqui que a lógica precisa estar Só precisamos ter certeza de que o mantemos limpo e eficiente. Então, finalmente, temos o ato do evento para começar a se sobrepor. Essa é uma verificação de sobreposição, uma verificação de colisão para toda a turma No nosso caso, isso pode ser qualquer coisa, desde a malha estática, o componente spring um ou o componente da câmera. É um pouco vago, então eu costumo não usar isso e lidaremos com as colisões por componente posteriormente. Então, podemos pegar esse, apertar delete, e vamos nos livrar dele. Para demonstrar o que o mapeamento de eixos está fazendo, vamos descer um pouco, então eu clico com o botão direito do mouse e arrasto para mover o gráfico Deseja clicar com o botão direito aqui e procuraremos a ligação de entrada que fizemos há pouco. Eu chamei o meu de Move Right. Temos duas opções diferentes aqui. Temos o evento do eixo e o valor do eixo. O evento criaria algo muito parecido com o evento fornecendo esse pino de execução para que fornecendo esse pino de execução pudéssemos orientar a lógica futura a partir disso A diferença com o valor do eixo é se clicarmos neste. Isso fornece apenas esse pino verde. Esse pino verde é um valor flutuante ou um valor em ponto decimal, e isso fornecerá um valor dependendo do que estamos pressionando Se não pressionarmos nada, obtemos zero. Se pressionamos para a esquerda, obtemos menos um, e se pressionamos para a direita, obtemos um positivo Na verdade, posso mostrar isso em uma demonstração muito simples, e recomendo isso para qualquer pessoa que esteja aprendendo novas partes do motor Unreal Vamos puxar esse pino de execução aqui, arrastá-lo para o gráfico e soltá-lo, e então vamos procurar a palavra string de impressão. Portanto, isso apenas fornecerá uma mensagem de depuração em nossa tela, no lado esquerdo, se pressionarmos play Então, podemos ver que aqui está enviando spam para a janela com a palavra Agora, para evitar que seja enviado spam porque está sendo executado 120 vezes por segundo, queremos reduzir isso e alterar a duração para 2 No momento, isso está sendo impresso por 2 segundos e vamos transformar isso em zero. Isso então se torna uma impressão mais constante por aqui, então agora é só imprimir a palavra olá. Obviamente, não queremos que isso diga olá. Queremos que isso nos mostre o que está sendo pressionado. Então, vou pegar o valor flutuante aqui, puxar desse pino e soltá-lo na entrada O motor Unreal é inteligente o suficiente para converter automaticamente nosso float em uma sequência de texto, então isso é um viés legível Então, se clicarmos em compilar e reproduzir novamente, você pode ver que agora isso está imprimindo zero, porque eu não estou pressionando absolutamente nada Se eu pressionar a seta para a esquerda, ela imprime menos um, a seta para a direita, obtenho um positivo e o mesmo para A e D. Então, podemos ver que está funcionando. Temos algo acontecendo aqui. Portanto, imprimir o valor mostra os dados, mas ainda é apenas um número , no que nos diz respeito. Então, vamos fazer algo muito rapidamente para tornar esse efeito algo visível Ainda não vamos adicionar movimento. Vamos chegar lá em um tópico separado. No entanto, se retirarmos nossa string de impressão, esse pino de execução aqui e pesquise defina a escala At três D. Queremos esse nó aqui, e tudo o que vamos fazer é afetar a escala geral do nosso ator com base na direção em que estamos pressionando. Para fazer isso, precisaremos apenas de um pouquinho de espaço no meio. Então, estou apenas movendo alguns nós por aqui. Vamos manter a matemática muito, muito simples. Isso é totalmente descartável e é apenas para visualizar partes do conceito , podemos pegar nossa escala de ator definida três D No entanto, podemos pegar nossa escala de ator definida três D, e podemos controlar isso pela direção que estamos pressionando. Então, podemos fazer a escala do ator zero menos um ou um E se adicionarmos alguma entrada analógica, poderíamos tornar esse valor muito simples Vamos fazer nosso movimento de obtenção que valorizamos aqui, então vou pegar isso pressionar Control em D para duplicar E vamos simplesmente conectar isso aqui. Então, como eu disse, muito, muito simples. Isso não será útil para nenhum tipo de cenário de caso de uso real. Eu só queria que você se familiarizasse um pouco com um pouco de projeto antes de mergulharmos no movimento Mas se clicarmos em compilar, isso apenas garante que tudo tenha sido verificado quanto a erros e esteja funcionando. Clique em salvar para não perdermos nada do progresso E uma coisa que acho que vou fazer é voltar à edição e depois às configurações do projeto. Eu conectei meu gamepad e, se voltarmos para a seção de entrada, basta adicionar uma nova entrada aqui, clicar neste botão e moverei o controle analógico para a esquerda Então, o manípulo analógico esquerdo, eu movi no eixo X, que é esquerdo e direito Podemos deixar isso como um número positivo se quisermos inverter o movimento analógico Então, por exemplo, se eu puxar para a esquerda, vou para a direita. Então é por isso que talvez queiramos adicionar um valor negativo. Mas como o analógico tem uma amplitude de movimento completa e é inteligente o suficiente para saber tomar a direção certa como positiva, a direção esquerda receberá automaticamente esse valor negativo Então, podemos fechar isso. Podemos entrar no modo de jogo Nós meio que quebramos o avião no momento. Então, no momento, estamos imprimindo zero na parte superior. que significa que estamos passando o número zero para o X, Y e Z da escala do nosso plano, e é por isso que não podemos vê-lo. Se eu pressionar A, então estamos invertendo o tamanho, então estamos vendo a parte inferior porque agora estamos fazendo do plano a escala desse negativo E se eu pressionar D, estamos tornando a escala do plano positiva um. A razão pela qual eu quero usar o manípulo analógico é que podemos visualizá-lo um pouco mais para que eu possa obter alguns movimentos suaves apenas movendo o manípulo analógico Se você ver o número no topo, isso está entre zero e menos um porque estou me movendo para a esquerda E se eu movê-lo para a direita, vamos entre zero e mais um. Então, apenas uma espécie de visualização de como podemos fazer uso desses valores e encaixá-los em uma lógica muito simples Novamente, estamos recebendo outra conversão. Isso está tomando nossa direção de movimento, então menos um, zero ou um, multiplicando isso por todas essas propriedades de escala Então, as propriedades da escala são irreais. Você tem o X, Y e Z. Só para visualizar isso em algo simples, como um Eu vou entrar aqui só para te mostrar isso. Se quiséssemos alterar as propriedades ou a escala desse objeto, poderíamos pegar apenas o eixo X, e você pode ver que está ficando mais longo. Poderíamos escalar no eixo y para torná-lo mais largo. E, novamente, podemos mudar o eixo z para torná-lo mais alto. Muito bom e simples, e isso é realmente tudo o que estávamos fazendo aqui no código, mas estamos apenas normalizando isso Então, todos eles são zero, menos um ou um, com base na entrada Então, como eu disse, código completamente inútil, descarte completo, mas espero que isso torne a entrada e a forma como podemos utilizar esse valor um pouco mais Feito isso, confirmamos que nossa contribuição está funcionando. A pornografia em si ainda não se move. Essa parte será a próxima a chegar. E no próximo vídeo, vamos transformar essa entrada em um movimento real do jogador. 6. 05 — PlayerMovement: Mas configurado e testado, é hora de fazer o avião realmente se mover. Mais uma vez, ainda faremos as coisas da maneira errada, primeiro movimento dependente da estrutura com uma espécie de movimento rápido, preencha, mas funcionará E você pode estar se perguntando por que estou ensinando conscientemente a coisa errada Isso ocorre porque esse código exato aparecerá em muitos lugares. Isso vem dos exemplos épicos de conteúdo oficial, que significa que você o verá em outros tutoriais que fazem referência a projetos mais antigos que você pode herdar, e tenho certeza de que em muitos Quando percebi isso, decidi que essa seria uma oportunidade perfeita para levar você a um ponto no final deste vídeo em que você verá o bug, entenderá por que isso acontece e saberá como corrigi-lo. Então, precisamos ainda estar dentro da nossa base de peões de sublinhado da BP Na verdade, podemos nos livrar de todo o código que temos no momento. Vamos nos livrar dessa escala e imprimir a sequência de caracteres. Isso foi apenas para demonstração e depuração. Para o movimento, isso é muito simples. Só precisamos considerar isso como nossa direção de movimento. Adicionaremos algum tipo de velocidade variável um pouco mais tarde e queremos compensar a localização do nosso avião a cada toque. Podemos fazer isso puxando do eventi, o pino de execução aqui Vamos pesquisar algo chamado set actor location. E esse será o nosso nó, que está dirigindo e controlando diretamente para onde nos movemos. Para fazer isso funcionar, precisamos calcular um deslocamento, levando em consideração a localização atual do avião e, em seguida, onde queremos que ele esteja Podemos fazer isso usando outra função embutida. Podemos clicar com o botão direito do mouse no gráfico do evento e eu vou pesquisar por Obter localização do ator. Se passarmos o mouse sobre elas quando as encontrarmos também, caso você não saiba, poderá ver dicas de ferramentas sobre o que essas funções fazem Então, isso retorna à localização dos componentes raiz, que sabemos ser nossa malha estática, essencialmente nos dizendo onde estamos em qualquer quadro. disso, retiraremos desse pino vetorial o pino amarelo aqui e procuraremos o símbolo de adição, ou você pode digitar add e queremos o nó AD. Podemos fazer algumas matemáticas vetoriais muito simples. Então, o que temos aqui é que nossa posição atual mais um deslocamento será igual a onde queremos estar, para que possamos conectar isso diretamente Um problema que enfrentamos no momento é que queremos controlar diretamente o eixo Y. Então, quando você estiver trabalhando com o Unreal, vou voltar ao nível apenas para dar um exemplo rápido aqui Quando se trata de direções e movimentos, se você não tiver certeza de para que lado deseja se mover, podemos simplesmente fazer algo como pegar nossa malha Coloque isso no nível e obteremos esse widget aqui, que nos mostrará as direções que você pode seguir dentro do Unreal A principal coisa a ser lembrada desde o início é que o vermelho, que é o eixo X, está à frente no mundo. Y, que é verde, é direita e para a esquerda no mundo ou para os lados, e Z, que é azul , é para cima e para baixo Isso é muito útil porque Unreal Engine os codifica por cores Então, se olharmos no painel de detalhes à direita, podemos ver aqui que temos X, Y e Z, e que tem um pequeno ícone de pílula mostrando vermelho, verde e azul Temos o mesmo para rotação e escala. E, como mencionei brevemente antes, essas três variáveis, localização, rotação e escala, são apenas uma estrutura que compõe o trans e cada uma dessas variáveis, como a localização, e é apenas uma estrutura de valores individuais de ponto flutuante. No exemplo em que mostrei que esse projeto se baseia, o avião obviamente se move de um lado para o outro e só de um lado para o outro, como antigos invasores espaciais, e estamos tentando recriar isso, então sabemos que precisamos nos mover no eixo Y. Então, de volta ao nosso código, isso significa que precisamos de alguma forma expor essa variável aqui Super simples de fazer. Podemos clicar com o botão direito do mouse no pino amarelo e temos a opção de dividir o pino da estrutura. E é por isso que mencionei que elas são chamadas de estruturas. Eles vêm em muitas formas diferentes, mas normalmente são apenas uma combinação de variáveis diferentes, criando um tipo específico de variável com um caso de uso diferente. Nesse caso, é a localização do movimento tridimensional. Se dividirmos o pino da estrutura, você pode ver que isso é revertido em seus valores individuais de ponto flutuante, o X, o Y e o z, e já temos nosso movimento configurado Esse é o nosso movimento para a direita, que podemos simplesmente conectar ao eixo Y. Então, o que estamos fazendo agora é pegar nossa localização atual e, a cada quadro, estamos adicionando um, zero ou menos um à direção Então, se pressionarmos play, podemos ver que agora temos algum tipo de movimento. Então, A e D me farão mover para a esquerda e para a direita, assim como os arokis esquerdo e direito Então, estamos um passo mais perto de onde queremos que esteja. Agora, isso nos coloca em uma pequena situação aqui, onde agora temos um problema em que este é um jogo dependente da taxa de quadros Então, vou mostrar algumas coisas sobre as repercussões disso e como você pode testar e ver isso por Então, no momento, lembre-se de que estamos movendo uma unidade por quadro se pressionarmos um botão. Então, se eu estiver rodando a 120 quadros por segundo, são 120 unidades por segundo. Um motor rL calcula as unidades em centímetros. Portanto, atualmente, isso está se movendo em torno de 120 centímetros/segundo Agora, se eu voltar ao modo de jogo, entrarei na janela principal aqui e apresentarei algo chamado comandos do console, onde podemos executar comandos simples para testar coisas. Eu também vou me livrar rapidamente desse avião de teste aqui. Então, de volta ao Playmode, clique no visor para ter certeza de que você tem controle total do E você quer encontrar a chave Tilda. Na maioria dos teclados, isso fica ao lado da linha de números. Se você pressionar a tecla Tilda, poderá ver um pequeno console aparecer na parte inferior da tela aqui Vou habilitar um comando de console muito simples, que é declarado space FPS Se eu pressionar Enter, podemos ver o lado direito da tela. Agora estou exibindo o número de quadros que estou executando por segundo. Vou pressionar a tecla Tilda novamente, digitar T dot max FPS ou One Word e depois espaço, e então vou definir isso para 30 Agora podemos ver no lado direito que limitou meus quadros a 30 quadros por segundo Agora, considerando o que mencionei há pouco, se a 120 quadros por segundo, eu estava movendo 120 unidades por segundo, isso agora significa que obviamente estou me movendo a 30 unidades por segundo. Então, estamos jogando o mesmo jogo, temos o mesmo código de movimento, mas o movimento é drasticamente diferente Se eu colocar isso de volta, vou reduzir para 300. Estou rodando a cerca de 300 FPS. Podemos ver que agora estamos nos movendo consideravelmente mais rápido porque agora estou movendo 300 unidades por segundo Vou colocar isso de volta para 30 e você pode ver o contraste. Agora, você provavelmente pode começar a ver por que isso não é o ideal. E isso é o que chamamos de dependência da taxa de quadros quando um jogo é executado especificamente com base no hardware Assim, jogadores com sistemas mais rápidos se moverão mais rápido e jogadores com sistemas mais lentos se moverão mais devagar É um bug que aparece em muito mais jogos do que você esperava. Então, antes de começarmos a pensar em criar o que é chamado de independência da taxa de quadros, vamos ajustar o resto do nosso código de movimento por enquanto , para que tenhamos tudo com que trabalhar No momento, mover apenas uma unidade por quadro obviamente não é muito notável, então vamos querer multiplicar nossa velocidade por um valor Podemos fazer isso com muita facilidade. Novamente, trabalhar com matemática dentro de plantas é relativamente simples Podemos extrair do nosso carro alegórico aqui o que queremos multiplicar. Arraste isso para o gráfico. Pesquise o asterisco, o símbolo de multiplicação ou a multiplicação de tipos, e podemos inserir esse resultado no Y. Isso significa que agora teremos nossa direção de movimento multiplicada por uma velocidade de movimento, que podemos definir como algo aleatório por enquanto, como dez, e esse será nosso novo deslocamento que aplicará cada quadro que Então, agora estamos nos movendo mais rápido, mas ainda teremos problema de independência da taxa de quadros em que se eu alterar a taxa de quadros em que estou executando, agora estou me movendo muito mais rápido. Então, isso está se tornando ainda mais perceptível. Eu só queria me concentrar aqui também. O que acabei de criar aqui é o que chamamos de número mágico. Esse número, nesse contexto, quando eu voltar a isso em um ou dois meses, é bem provável que você esqueça exatamente o que esse número estava representando sem olhar para trás no código. Eu lhe dou a pergunta, por que isso era dez? Por que não foi 100? Por que não foram 1.000 e assim por diante. Para aliviar isso um pouco, e novamente, focando nessa boa prática de programação e tentando manter nosso código organizado desde o início Vamos extrair esse pino verde aqui, e eu vou fazer algo chamado promover isso para uma variável, e você pode ver a opção aqui para promover isso para uma variável. Então, clicaremos nisso. No lado esquerdo, é onde as variáveis residem. Podemos pegar esse nome, e eu vou renomeá-lo para velocidade de movimento Então, agora, de relance, no mínimo, isso nos dá uma ideia do que esse valor está fazendo Então essa é a velocidade na qual esperamos nos mover, multiplicada por uma direção sendo adicionada à nossa localização ativa Ele começa a parecer um pouco mais como um romance em uma página, e você tem uma ideia do que o código fará, mesmo sem investigá-lo completamente, que é o que queremos que nosso código faça, torne-se legível por humanos Portanto, temos nossa variável de velocidade de movimento. Podemos clicar em compilar aqui, apenas para verificar se o número dez está preenchido porque já tínhamos esse valor como um número mágico Então, de volta ao bug da taxa de quadros. Precisamos garantir que, independentemente da velocidade em que nosso sistema esteja funcionando, obtenhamos o mesmo tipo de movimento. Isso não é apenas para o resultado do jogador, mas como designer, quando estamos criando nosso jogo, estamos ajustando tudo. Queremos que tudo seja tão suave, reativo e responsivo quanto esperávamos Ajustamos todo o jogo para ser jogado de uma maneira específica. E, obviamente, isso será completamente arruinado se alguém que estiver jogando em um sistema duas vezes mais rápido que o nosso obtiver um resultado diferente O que precisamos para isso é algo chamado de segundos Delta, às vezes chamado de Delta simplesmente o número de segundos que passaram desde o último quadro. Em vez de usar esse pino aqui para nosso cálculo, porque, é claro, ele teria fios sobrepostos e começaria a introduzir o código de espaguete Vamos clicar com o botão direito do mouse no gráfico e pesquisar os segundos Delta. Você pode ver aqui que temos a opção obter segundos do World Delta, e podemos conectá-la e fazer uso dela. Simplesmente, queremos pegar todos os valores que temos aqui e multiplicá-los pelos nossos segundos Delta. Então, o mesmo de novo. Vamos pesquisar multiplicar, inserir isso, inserir o cálculo no resultado e chegaremos mais perto do que queremos Agora, permita-me demonstrar rapidamente o que segundos Delta estão realmente fazendo e o que o valor representa. Uma maneira muito rápida de fazer isso. Quero colocar uma sequência de caracteres impressos, como vimos antes. Vou definir isso como zero para a duração, pegar o nó de segundos Delta, duplicá-lo e conectá-lo apenas para que possamos ver o que está sendo impresso Nos meus 300 FPS, não vamos usar esse número, então vou limitar isso de volta para 120 A 120 FPS, estamos obtendo um valor em torno 0,008 segundos entre cada quadro Se eu limitar isso de volta para 60, veremos isso cair para 0,016 E então, se reduzirmos isso ainda mais para 30, obteremos um número de 0,033 Então, aproximadamente, não exatamente, mas aproximadamente metade do número cada vez que reduzimos a taxa de quadros pela metade. E veja como isso é útil e como corrige nossos problemas dependentes da taxa de quadros. Se você estiver executando a 30 FPS, cada quadro o moverá ainda mais, mas essas são etapas maiores, mas você está dando menos etapas por segundo Já a 120 FPS, cada quadro está movendo você menos Essas são etapas menores, mas você está dando quatro vezes mais etapas dentro delas. E o resultado final é que a distância total por segundo permanece praticamente a mesma. E isso é se você está rodando a 30 FPS ou 120 FPS. Temos independência de taxa de quadros, e essa é a diferença entre um jogo que parece justo em todos os hardwares, em comparação com pessoas experiências diferentes em sistemas superiores ou inferiores. Uma coisa a observar, como agora estamos multiplicando nossos valores por esse número incrivelmente pequeno, a velocidade em que estamos nos movendo obviamente parecerá muito mais lenta, muito lenta, quase muito lenta Então, precisamos entrar e considerar isso na velocidade de movimento. Vou aumentar isso para algo como 500 em vez de dez, clicar em compilar e jogar, e vai parecer mais ou menos o mesmo O principal, novamente, é que o que estamos vendo é um salto de 30 a 120 FBS Parece mais suave, mas não estamos visivelmente indo mais rápido A única diferença que estamos vendo é a suavidade do movimento devido à taxa de quadros que estamos vendo. Então esse é realmente o objetivo aqui. Então, com isso, o movimento funciona. Resolvemos o problema da estrutura, mas na verdade não está bem resolvido . Podemos notar que é muito rápido quando o movemos. Se pressionarmos uma direção, estaremos instantaneamente a toda velocidade. Assim que lançamos, somos interrompidos instantaneamente. Não há aceleração, não há impulso. Veículos reais não funcionam dessa maneira. Até mesmo nossos filhos mais velhos terão algum peso, então precisaremos considerar adicionar aceleração suave E toda essa abordagem que estamos adotando no momento, a localização do ator no set. Fazendo isso, cada quadro não tem integração física, nenhuma resposta de colisão adequada e está perfeitamente bem É por isso que ele é fornecido nos exemplos de conteúdo do Epics. O padrão funciona porque é simples, não porque é a melhor prática. Então, temos movimentos. Entendemos o bug de estrutura que tivemos e como corrigi-lo, e sabemos por que essa abordagem é comum e por que não é ideal. Em seguida, moveremos os sites. Vamos adicionar um pouco de aceleração, inclinação rotativa, geralmente com o objetivo de algo que pareça mais com uma aeronave Se você quiser experimentar, pode sempre tentar adicionar movimento vertical É o mesmo padrão. Basta usar o eixo diferente, o eixo X em vez do Y, ou adicionar a ele. Provavelmente, você também precisará introduzir uma nova vinculação de entrada , uma pequena dica. 7. 06 — suavidade em movimento: No momento, nosso movimento funciona tecnicamente, mas parece muito robótico Início instantâneo, parada instantânea. Abordaremos isso neste vídeo adicionando pouco de aceleração e rotação bancária, para que pareça que você está realmente pilotando algum tipo de aeronave Arcade Usaremos algo chamado interpolação, que é a suavização entre dois pontos ao Essa também será a próxima etapa para herdar os bugs do épico conteúdo oficial de aprendizagem Nós o encontraremos, reconheceremos e o corrigiremos um pouco mais tarde. Então, agora, o problema é que nossa velocidade está sendo tirada diretamente da entrada. Aqui, temos o movimento para direita multiplicado pela velocidade do movimento Então, se estivermos pressionando para a direita, isso é um multiplicado por 500. Vamos direto para a velocidade de 500 unidades por quadro. Se estivermos pressionando para a esquerda, isso é menos um multiplicado por 500, então estamos fazendo com que menos 500 sejam aplicados diretamente à nossa velocidade de movimento É por isso que obtemos esse início instantâneo e parada instantânea. É claro que, assim que soltamos uma tecla, multiplicamos o valor por zero, então vamos direto para a velocidade de movimento de 500-0 Para um movimento suave, precisaremos de dois valores diferentes. Queremos uma velocidade alvo, que é onde queremos estar, e precisamos nossa velocidade atual, que é onde estamos no momento. Ou use-os para se mover gradualmente entre nossa velocidade atual e nossa velocidade alvo. Para começar, podemos criar facilmente um novo flutuador ou a velocidade atual que vamos rastrear Podemos pegar nossa velocidade de movimento aqui, clicar com o botão direito do mouse ou pressionar Control em D para duplicar. Vamos chamar isso de velocidade atual. E o que faremos é pegar esse valor que estamos calculando aqui, essencialmente nossa velocidade de movimento, e esse será o alvo que usaremos um pouco mais tarde Se quiséssemos arrumar isso, definitivamente poderíamos tornar isso mais legível visualmente Se eu mudar isso, podemos pegar esse cálculo aqui. Vou pressionar Control em X para cortar isso, controle em V para colar acima, vamos extrair isso aqui e vamos promover isso para uma nova variável. Vamos promovê-lo para algo que chamaremos de velocidade alvo. E podemos conectar isso aqui. Você verá por que, em um momento, isso não está realmente mudando nada no momento, mas tornará as coisas um pouco mais legíveis Agora, além de esconder as coisas para que tenhamos um pouco mais de espaço para trabalhar, lembre-se de que precisamos reconectar nossa velocidade alvo que estamos calculando agora A única diferença é que basicamente demos um nome a esse alfinete. Então, novamente, é um pouco mais legível. Vamos atingir nossa velocidade alvo. E se colocarmos isso diretamente no pino de fluxo Y que agora está exposto, isso automaticamente conectará isso para nós. Algo que você me verá fazer com bastante frequência, também, é o que eu fiz ali mesmo. Então, esses pinos, meio que os fios estavam flutuando um pouco Se você pegar vários nós, pressione um taco que alinhará automaticamente os fios para Assim, podemos manter as coisas um pouco mais arrumadas à medida que avançamos. Outra coisa que é útil saber é que se você mouse sobre o pino aqui, por exemplo, e pressionar um taco sem realmente pegar as notas, ele pegará o nó que está conectado e também os alinhará Então, não é algo que você absolutamente precise fazer, mas eu só estou mencionando isso porque eu percebo que eu faço isso com memória muscular, então eu vou fazer isso enquanto estou falando às vezes E eu só queria que você soubesse os atalhos que estou usando Ok, então de volta ao tópico principal. Queremos suavizar esse movimento com uma interpolação flutuante Se clicarmos com o botão direito do mouse no gráfico de eventos aqui, procuraremos por F interp two Essa é uma interpolação baseada em flutuação para um determinado valor. Podemos ver aqui algumas coisas que foram dadas. Então, começamos com nosso valor atual, que é, como mencionei, onde estamos agora. O alvo é onde queremos estar para preenchê-los diretamente. Já temos esses valores e eles são nomeados de acordo. Assim, podemos pegar nossa velocidade atual e colocá-la aqui na corrente. Então, vamos sair da nossa corrente e atingir nossa velocidade alvo. Então, basta arrastar e soltar isso também. Você pode ver que, em seguida, precisamos inserir o horário Delta. Então, temos os segundos Delta aqui. Vou selecionar esse , pressionar control, na verdade, duplicar com meu mouse aqui embaixo, e podemos conectá-lo aos segundos Delta. O tempo Delta aqui mantém a taxa de quadros de interpolação E independente, com algumas peculiaridades Mas, novamente, voltaremos a isso quando virmos esse problema e o abordaremos mais tarde. E, finalmente, temos a interação que controla a rapidez com que aceleramos em direção à velocidade alvo que nos é dada Valores mais altos aqui significam uma resposta mais rápida. Valores mais baixos significam que parecerá um pouco mais flutuante. Vou começar com o valor de quatro, que funcionou perfeitamente bem nos testes. E então, é claro, não queremos nenhum número mágico em nosso código. Então, vamos partir daqui. Vamos promover isso para uma variável. Vou dar a este um nome sensato algo como movimento interpreta velocidade Então, agora temos os quatro F interp dois. O resultado dessa interpolação se tornará nosso novo valor de velocidade atual Muito importante aqui. Vamos precisar nos dar um pouco mais de espaço. Vou remover a sequência de caracteres impressos aqui. Não precisaremos mais disso, e vamos passar isso para cá por nove. Vamos evitar qualquer código de espaguete e vamos manter as coisas arrumadas à medida que avançamos Isso precisará ser calculado aqui. Precisamos primeiro da nossa velocidade alvo, seja, o valor que sabemos que vamos atingir E também precisamos definir agora. Então, usando um nó como esse definindo o valor da nossa velocidade atual. Algo que acho que ainda não abordei é que temos formas alternativas de trazer nossas variáveis para o gráfico. Se mantivermos pressionada a tecla control no teclado e agarrarmos, por exemplo, a velocidade atual e arrastá-la para o gráfico, isso fornecerá um nó. Esse nó fino é chamado de getter. Basicamente, fornece o valor. Nós podemos ler isso. Está obtendo valor para nós. Se mantivermos pressionada a tecla Alt e fizermos a mesma coisa novamente, pegue a velocidade atual e arraste-a para o gráfico, mas agora segure a tecla Alt. Isso está fornecendo algo chamado setter. Então, isso é o oposto. Isso nos permite escrever no valor que temos aqui. Então, isso nos permite ler o valor. Isso nos permite escrever no valor. Queremos manter a versão gravável aqui na velocidade atual, então vou me livrar do getter E queremos levar nosso valor aqui. Como acabei de dizer, é assim que nossa velocidade atual será rastreada Então, vamos conectar isso à velocidade atual, e só precisamos ter certeza de conectar os pinos de execução aqui E só para tentar encerrar isso e garantir que isso faça sentido, porque eu entendo que isso pode parecer um pouco confuso Precisamos saber, antes de tudo, o que estamos pressionando e a que velocidade estamos tentando atingir, é por isso que atualmente estamos definindo primeiro a velocidade alvo. Então, se imaginarmos que estamos calculando isso desde o primeiro quadro, já sabemos que nossa velocidade alvo é movimento multiplicado por ou mais precisamente, nossa direção pela velocidade de movimento, multiplicada por Delta, então obteremos um valor de 500 multiplicado por qualquer valor pequeno baseado na Portanto, temos uma meta clara a ser alcançada. A primeira vez que executarmos isso, obviamente, velocidade atual provavelmente será zero. Então, vamos partir de nossa velocidade atual de zero, então não estamos nos movendo para, digamos , 100 unidades de movimento para fornecer um bom número claro. Vamos considerar o tempo de Dw novamente para manter esse quadro independente, mais ou menos, e temos nossa velocidade de movimento, a velocidade de movimento de interpolação , para fornecer diferentes níveis Então, no próximo quadro, obviamente, a velocidade atual teria sido calculada com base nisso para ser um pouco maior. Então, vamos partir dessa velocidade um pouco maior. Digamos que dois ou três, e então vamos partir desse valor de dois ou três, ainda tentando chegar às 100 unidades de velocidade que precisamos alcançar. E vamos fazer isso continuamente ao longo do tempo, que proporcionará essa suavização Então, a última coisa é que não queremos usar a velocidade alvo diretamente. É só isso que queremos usar seja qual for a velocidade no momento. Então, vamos deletar esse. Vamos pegar nossa velocidade atual. E, novamente, vamos arrastar isso para nosso pino verde aqui, e isso o conectará automaticamente para nós. E é isso. Está praticamente pronto para testar o movimento suave. Então você pode ver aqui, enquanto eu estou indo para frente e para frente, no momento em que eu solto a tecla, temos um pouco de suavização acontecendo à medida que descemos a nenhuma velocidade Então, temos alguma desaceleração e aceleração chegando aqui Agora, como estamos fazendo isso com o tempo, o movimento pode parecer um pouco mais lento Então, uma das outras coisas realmente úteis de promover nossos números mágicos em variáveis é que eu posso simplesmente pegar a velocidade de movimento. Talvez eu possa dobrar isso, então vamos definir isso para 1.000 porque está um pouco lento. Não precisei ler o código. Eu não precisava descobrir onde isso estava acontecendo. Isso é muito bem chamado, então eu sei que isso está controlando a velocidade com que eu vou me mover. Eu posso apertar play. Eu posso testar isso novamente, e temos um plano de sensação completamente diferente acontecendo. Então, isso está se sentindo muito melhor. Isso realmente exagera um pouco mais a aceleração e a desaceleração. E, novamente, tudo isso foi feito alterando uma propriedade completa do sistema geral de movimento simplesmente pegando a velocidade de movimento e conectando-a Obviamente, adicionamos o movimento suave, é por isso que precisávamos fazer essa emenda. Se você quiser brincar com coisas, pode fazer algo semelhante, pegue a velocidade de interpolação do movimento e veja se você quer que ela leve mais ou menos tempo para atingir o valor final, velocidade atual que estamos Então, esses são apenas alguns ajustes variáveis aqui com base em como você deseja que seu jogo, seu avião seja preenchido Um princípio de design que eu ouvi muito cedo e que sempre ficou comigo é sempre tentar exagerar a variável Então, se você não tem certeza do que eles estão fazendo, ou não tem certeza se queria que fosse muito mais rápido ou muito mais lento é o dobro ou o triplo do valor que você está trabalhando Eu poderia definir esse 4-12 porque você quer atingir um extremo primeiro, descobrir se funciona, se está muito alto muito baixo e depois refiná-lo no meio Então, eu posso ver que está quase me sentindo bem novamente. Há alguma aceleração e desaceleração, mas não muita Então, o que eu talvez queira fazer é reduzir isso para seis, porque 12 é definitivamente muito alto, e estamos nos sentindo um pouco melhor aqui. Agora, como eu disse, para mim, gosto muito da sensação disso aos quatro anos, mas apenas um princípio geral de design é levar o valor ao extremo, duplo, triplo, metade de algo , seja qual for o caso, e você rapidamente poderá se concentrar em como queria que sua propriedade parecesse Para meus propósitos, vou manter a velocidade de interação do movimento em quatro e podemos passar para o próximo recurso Então, agora adicionando a rotação bancária. Na verdade, isso vai ser muito simples. É essencialmente uma repetição do que acabamos fazer com algumas funções ligeiramente diferentes. Essencialmente, à medida que nos movemos de um lado para o outro, queremos que o avião se incline um pouco para que pareça um pouco mais com uma aeronave real Uma rápida atualização sobre o eixo aqui. Acho que ainda não toquei nisso no outono. Vou pegar uma malha estática muito rapidamente. Eu não preciso acompanhar. Isso é só para visualizar o que estamos fazendo. Vou pressionar E dentro do ponto de vista para entrar no modo de rotação, e podemos ver nossos eixos Então, eu mencionei antes, temos essa transformação, a localização, rotação e escala que compõem a posição no espaço mundial do nosso ator. Os locais são muito simples. Temos X, Y e Z, que são para frente, para os lados, para cima e para baixo. Rotação, é relativamente simples. mesma coisa. Temos três cores. Temos o vermelho, o verde e o azul, então o X, o Y e o z. Mas se passarmos o mouse sobre eles, podemos ver aqui que eles realmente têm seus próprios nomes exclusivos Temos o rolo, o tom e a perna. Agora, isso não importa muito, mas se você estiver tentando ajustar esses recursos, adicione sua própria funcionalidade e nem terá certeza de quais eixos devo girar ou algo Eu só queria mostrar um pequeno visual aqui que, na verdade, é muito simples de descobrir. Então, nesse caso, eu quero que o avião se incline em uma direção com base em como ele está se movendo Então, se eu tentar apenas algumas coisas aleatoriamente, se eu tentar a verde e ver o que isso faz, podemos pegar o valor verde aqui e eu vou deslizar isso para fazer isso girar E podemos ver que isso nos dá uma espécie de rotação para cima e para baixo do avião aqui. Isso provavelmente seria bom se você estivesse avançando e retrocedendo Talvez você possa adicionar um pouco disso para exagerar o movimento de avançar e retroceder Se eu pegar o z e fizer a mesma coisa, eu só pego aqueles que eu sei que não funcionam para começar e os tiro do caminho Podemos ver que isso está girando em torno dos eixos do avião. Então, novamente, não será muito útil a menos que estejamos fazendo quatro tons ou algo assim. Então, o que queremos usar será o eixo X aqui. Então, à medida que nos movemos para a esquerda e para a direita, vamos querer inclinar um pouco e rolar assim, com base na direção em que estamos indo. Então é assim que você pode facilmente entrar, brincar com os diferentes widgets aqui, girar em uma determinada direção e ver qual eixo você deseja aplicar a rotação Como eu disse, isso foi apenas para demonstração visual. Vou deletar a malha estática. Vamos voltar para a base da panela. Mova isso um pouco e podemos continuar com a rotação. Para a rotação aqui, temos algumas funções muito semelhantes que já usamos. Vamos extrair a localização do ator do conjunto, e você provavelmente pode adivinhar que vamos pesquisar algo chamado rotação do ator do conjunto. Isso é muito parecido, atualizações na rotação, e isso será em cada quadro porque estamos lançando isso no evento Agora, vamos querer usar uma função muito semelhante também, queremos usar uma interpolação para Agora, para rotação, não usamos a interpretação F, vamos usar algo chamado interpretar dois. Então, estamos clicando com o botão direito aqui. Pesquise a interp two, y, a rotação, e vamos pegar essa aqui A outra razão pela qual estamos fazendo isso dessa maneira que poderíamos potencialmente pegar apenas um único valor flutuante porque só queremos fazer isso no X. Poderíamos fazer algo muito semelhante aqui e usar uma interpretação F. Agora, estou mantendo isso em paridade, linha por linha , com o projeto de exemplos de conteúdo do Unreal Engine Então é exatamente assim que eles fizeram. Eles usaram uma interpretação F para a localização e uma interpretação R para a rotação. Então, eu queria mostrar novamente o código que existe e como podemos corrigi-lo caso surjam dúvidas, por que estamos fazendo isso de forma um pouco diferente Mas a principal coisa aqui é que isso ainda é muito útil porque podemos ver que obtemos as mesmas propriedades que precisamos para nos alimentar. Temos uma rotação atual, então, onde estamos no momento, temos uma rotação alvo para a qual queremos girar E temos o tempo Delta para tornar essa taxa de quadros independente, novamente, mais ou menos. E então temos a velocidade de intercalação, que é a suavização Então, a corrente é realmente muito simples. Temos outro ajudante muito semelhante ao que usamos antes Se clicarmos com o botão direito do mouse no gráfico de eventos e pesquisarmos por Obter rotação de atores. Isso fornecerá, como a localização get actor que usamos, a rotação do ator nesse determinado quadro. O alvo é uma espécie de número aleatório arbitrário, e eu digo que só porque tudo o que o exemplo épico fez foi pegar a velocidade atual, então vou controlar o arrasto da velocidade atual para o gráfico para obter a velocidade atual que estamos movendo e multiplicá-la então vou controlar o arrasto da velocidade atual para o gráfico para obter a velocidade atual que estamos por um valor Então, a partir daqui, vamos selecionar multiplicar. E eu acho que o deles era algo como 1,5. Então, vamos pegar qualquer velocidade em que estamos nos movendo, seja um valor positivo ou negativo, multiplicando isso por 1,5 E esse será o alvo para o qual queremos girar no eixo x. Algo que eu queria te apresentar. Nós já vimos aqui. O uso do pino de estrutura dividida para levar nosso vetor de três pontos até seus pontos flutuantes individuais. O rotador é exatamente o mesmo. Poderíamos simplesmente clicar com o botão direito pino da estrutura dividida e colocá-lo no X, Y e Z. Isso pode ficar um pouco confuso quando você tem tantos flutuadores diferentes Então, uma coisa que pode ser bastante útil e, mais do que tudo, é apenas para organizar o código, é que vamos extrair do alvo aqui e procurar algo chamado make Queremos essa opção inferior aqui, e ela funciona exatamente como o nome sugere. É criar um rotador a partir de X, Y e Z individuais. Ele mantém esses dois flutuadores sozinhos, então são mais fáceis de ler, e nos permite simplesmente inserir nosso valor aqui no X, apenas uma maneira diferente de chegar ao mesmo objetivo que fizemos Nenhum deles é menos ou mais eficiente e, na verdade, pode se resumir ao que é mais legível em um determinado caso Eu não diria que isso é muito ilegível, porque é apenas um vetor que dividimos . Onde está isso? Já existem vários carros alegóricos, e dividir mais carros alegóricos neles acabou por se desenrolar um pouco Como vimos anteriormente, queremos nosso resultado final seja a nova rotação que temos aqui, então vou pegar essa interpolação e inseri-la no novo E isso só nos deixa com algumas coisas para preencher. Então, queremos nosso horário Delta, então eu vou vir aqui, pegar um delta mundial de segundos, pressionar Control ID aqui para duplicá-lo e conectá-lo E então só precisamos da nossa velocidade de interpolação. Então, novamente, isso está se movendo no meio. Acho que estou testando que um valor de cerca de dez funcionou muito bem, e esse é um daqueles valores que você simplesmente volta e ajusta para obter a sensação de rotação exatamente como deseja Novamente, não há números mágicos, então, a partir daqui, promoveremos uma variável. Dê a esta o nome de velocidade de interposição de rotação. E com isso, estamos praticamente prontos para testar isso. Embora uma coisa tenha se destacado para mim. Isso atua essencialmente como um fator de inclinação ou força de inclinação, em vez de ter esse número mágico que vamos extrair daqui, de remoto para variável Vou usar o fator Tilt, que agora está realmente pronto para ser testado Assim, podemos clicar em compilar, pressionar play e ver que temos alguns serviços bancários Agora temos outro problema, que eu esqueci completamente que iria acontecer Então, vamos corrigir isso em um momento, mas no setor bancário, a rotação está realmente funcionando. Então, agora que eu potencialmente causei enjôo a todo mundo, a câmera está inclinada com o avião Confirmamos isso, no mínimo. O motivo pelo qual os problemas com a câmera acontecem é que a câmera herda a rotação da mãe Nós realmente vimos isso na hierarquia. As câmeras estão conectadas à mola, o braço da mola à malha estática, e estas estão acompanhando toda a rotação e localização aplicadas à mistura estática. Isso é muito simples de corrigir. E uma das razões pelas quais eu queria usar o hum de mola que esqueci de marcá-lo com o hum de mola selecionado no painel de detalhes no lado direito Esse componente exclusivo nos fornece uma solução A Epic sabia que esse tipo de coisa seria um problema em potencial. Então, eles nos deram algumas caixas de seleção aqui. Podemos desmarcar o tom, o U e a rotação herdados. Lembre-se dos nomes dos X, Y e Z da rotação. Então, se os desmarcarmos, isso basicamente significa que não permita que o braço da mola siga a rotação do componente principal E como as câmeras são derivadas do braço de mola, isso também se aplica ao componente infantil da câmera. Então, se clicarmos em compilar, pressionarmos play, podemos entrar e ver que podemos ver bem a rotação E não estamos recebendo aquele movimento de câmera potencialmente nauseante que tínhamos há pouco Outra coisa que acabei de perceber com a goma de primavera selecionada, eu também tinha essa marca marcada. Faça o teste de colisão Se você teve algum problema em que a câmera parece estar se movendo ou sendo jogada no chão ou algo assim, isso é potencialmente porque o teste de colisão está o teste de colisão O que está acontecendo aqui só para visualizar isso? Se alguma coisa for detectada entre a câmera e a coisa que ela está vendo aqui, então algo com colisão neste ponto no braço vermelho da mola, aí que o teste de colisão está acontecendo Se alguma coisa passar por isso, é aí que a câmera tentará se mover automaticamente para fora do caminho ou se esconder atrás de algo para evitar a colisão Muito útil para coisas como jogos em terceira pessoa em você pode ter a câmera roçando na parede e ela ficará um pouco mais perto do jogador . Então, esse é um recurso muito bom. No entanto, em um jogo como atirar neles , como estamos criando, podemos ter problemas em que a câmera parece instável se projéteis traços e coisas assim passarem pela câmera, pela linha da E, novamente, isso é outra coisa que você vê em projetos iniciantes em que a câmera está meio instável ou com falhas Provavelmente é porque eles têm algum tipo de teste de colisão acontecendo entre a câmera e o que você está olhando Então, vamos desligar isso. Não precisaremos disso para esse tipo de jogo. Com isso feito, a câmera permanece nivelada. O avião pousa naturalmente, parece muito melhor. Então, agora finalmente podemos ver onde exemplo da Epic se divide um pouco. Só queria mencionar que isso não é uma sombra o projeto de exemplo, para a Epic ou algo parecido. Estou mencionando isso apenas porque percebo que essa é uma oportunidade perfeita de ensino, algo que é amplamente abordado usado por tantos canais de tutoriais diferentes, inclusive eu, que você verá um código quebrado até mesmo em fontes oficiais Então, saber disso e ser capaz de cuidar disso será muito valioso. Então, o problema que estamos enfrentando no momento é se vamos jogar no modo. Com uma taxa de quadros alta, vou reativar minhas estatísticas de taxa de quadros Então, 120 FPS, isso parece meio bom. No entanto, se eu reduzir isso para 30 FPS, concentre-se em quanto a rotação está sendo aplicada Então, novamente, você pode ver que não é apenas o caso de um deles parecer um pouco mais suave e um deles parecer um pouco menos suave devido à taxa de quadros Isso é literalmente uma diferença na mecânica, mesmo código, mesma entrada, rotação completamente diferente A 30 FPS, estamos quase girando a asa pelo chão, dependendo da distância entre o avião e o E essa é uma dessas coisas. Nem mesmo está quebrando a jogabilidade. Mas se você configurou um sistema para ter uma aparência super suave e exatamente como você deseja, ele parece ser o mais atraente para o jogador , mas alguém um sistema de especificações mais baixas joga com um sistema de especificações mais baixas joga e recebe o segundo resultado Obviamente, você ficará desapontado, pois eles não estão tendo a experiência que você pretendia E é por isso que é muito importante focar nisso. E isso é o que eu quis dizer com esse bug existe nos exemplos de conteúdo oficial da Epic, mesmo código, mesmo problema, enviado na documentação atual E é por isso que confiar cegamente até mesmo em exemplos oficiais, até mesmo documentação inicial de piedade, pode ter bugs Portanto, sempre teste casos extremos e fique atento a coisas assim. Isso é o que eu realmente estou tentando transmitir. Mencionado anteriormente, vai ser um pouco longo demais para esse tópico. Então, isso é algo que vamos corrigir um pouco mais tarde, e vamos reconstruir completamente o sistema de movimento Mas, por enquanto, vamos apenas reconhecer que o bug existe. Ainda é perfeitamente possível trabalhar com isso. É uma base perfeita para construir ainda mais. Voltaremos e reformularemos totalmente o sistema de movimentação e corrigiremos todos os bugs quando terminarmos E agora que vimos a recompensa por não usar números mágicos, temos nossa velocidade de movimento, controlando o quão rápido você pode ir, velocidade de interpolação de movimento, que é rapidez com que você atinge essa velocidade, nosso fator de inclinação sobre o quanto o avião se inclina nas diferentes velocidades e até mesmo a velocidade de interpolação de rotação, que é a rapidez com que chegamos a esses valores de inclinação. Tudo isso é ajustável sem tocar na lógica. Se você quiser uma ação rápida de arcade, podemos aumentar a velocidade de interação Se você quiser um espaço lento e flutuante, pode abaixá-lo. A sensação do jogo , então, vem dos números. Então, podemos deixar isso aí. Temos um movimento suave, um tanto satisfatório, com um bom sistema bancário E sim, há o bug da taxa de quadros ao qual voltaremos, mas pelo menos sabemos disso e corrigiremos isso mais tarde. Em seguida, podemos atualizar para o sistema de entrada aprimorado. Este é o substituto moderno da Unreal para o sistema de entrada antigo que estamos usando atualmente Se você quiser experimentar, como eu disse, agora você tem todos esses valores prontos para usar. Tente adicionar um pouco mais de inclinação à rotação e potencialmente, adicioná-la com os movimentos para frente. O mesmo padrão, eixo diferente para a rotação e o movimento, se você ainda tiver isso em uma direção. 8. 07 — Input aprimorado: Configuração do movimento e trabalho até um ponto testável. Lembre-se de que o sistema de entrada antigo que estamos usando, como mencionei, está obsoleto A entrada aprimorada é a substituição moderna. Há uma configuração um pouco mais inicial, mas é significativamente mais flexível Temos coisas como esquemas de controle com troca automática, zonas mortas integradas, revinculação de tempo de execução e todas as coisas que você mesmo precisaria codificar usando o Então, vamos começar a migrar. A primeira diferença principal é que o sistema de entrada aprimorado , na verdade, tem seu próprio conjunto de classes. Então, volte para a pasta de plantas, clique com o botão direito aqui ou pressione Control Shift em n para criar uma nova pasta, e chamaremos isso de entrada A entrada aprimorada divide as coisas em duas partes. Temos nossas ações de entrada, que definem o que pode acontecer como disparar, mover, reiniciar. E então temos algo chamado contextos de mapeamento de entrada, que definem quais botões acionam as ações mencionadas anteriormente, fornecendo uma separação de preocupações E a razão pela qual essa separação se mostra útil é que isso permite que os esquemas de controle mudem sem a necessidade de reprogramar toda a lógica do jogo No código, podemos simplesmente chamar o sistema de entrada para alternar entre controles de menu, controles jogabilidade, controles de veículos, seja o que for. Eles podem compartilhar os mesmos mapeamentos de ações com os botões específicos, mas podem ser executados em contextos diferentes Uma linha de código e temos tudo trocado. Dentro da pasta de entrada, vamos clicar com o botão direito e eu vou para a categoria Entrada aqui. Podemos ver que temos a seção de ação de entrada, então criaremos uma delas. Dê a isso o nome de IA Underscore Fire. Vamos selecionar este controle mamário , na verdade, para duplicar. Precisamos de mais dois deles, então vamos duplicar isso duas vezes e chamaremos um IA de sublinhado de movimento e o outro de sublinhado de IA Em seguida, queremos abrir nossa classe IA underscore move. Vamos clicar duas vezes para abrir isso. E a principal coisa que queremos ver é que aqui temos o tipo de valor. Por padrão, isso é definido como booleano digital ou bola, e isso é muito semelhante ao que configuramos nas configurações do projeto com os mapeamentos de ações Precisamos excluí-los de qualquer maneira. Vamos voltar para Editar, configurações do projeto. Vamos descer para inserir novamente. E só para contextualizar, o booleano digital que seria ativado ou desativado seria se tivéssemos criado um mapeamento de ações aqui Por exemplo, poderíamos ter criado algo chamado fogo, amarrado isso a um botão e feito esse disparo toda vez que quiséssemos chamar um projétil Enquanto estivermos aqui, também vou me livrar dos mapeamentos de ações para que não tenhamos mais nada Isso também causará um pequeno bug em nosso código, mas facilitará a localização e o aprimoramento das coisas quando estivermos fazendo nossa atualização de código Então, vamos apenas pressionar Delete para nos livrarmos de nossos mapeamentos de acesso também Novamente, isso evita automaticamente que possamos fechar isso e voltar para o sublinhado IA Nossas ações de entrada de disparo e reinicialização. Ambos precisam de barras digitais, e é por isso que eu não as abri Eles estão perfeitamente bem por padrão. Ou estamos apertando o botão de disparo ou não. É o mesmo para o botão de reinicialização. Para o movimento, porém, queremos reduzir isso e usar esse flutuador D do eixo um, fornecendo essencialmente a mesma coisa que um mapeamento de eixo, fornecendo um valor de menos um a um positivo ou zero se nada estiver sendo pressionado Então essa é a única mudança que precisamos fazer dentro da nossa ação de entrada. Podemos pressionar Salvar. Podemos fechar este e voltar para nossa pasta de entrada. Então, agora queremos chegar ao nosso contexto de mapeamento. Isso vai ser quais botões serão acionados, quais ações. Se clicarmos com o botão direito do mouse na pasta aqui, voltaremos para a seção de entrada e, desta vez, criaremos um contexto de mapeamento de entrada. A convenção de nomenclatura será IMC. Sublinhe e, em seguida, o nome da coisa pela qual isso será responsável Só teremos um tipo de entrada neste projeto mais simples. Então, vou chamar isso de principal para nossa entrada principal. Clique duas vezes para abrir isso e podemos ver como funciona. Agora, isso meio que representa as configurações do projeto que estávamos editando anteriormente. No canto superior esquerdo, queremos clicar nesse botão de adição e soltá-lo. Precisamos tornar cada uma dessas entradas única, é por isso que ela está sendo classificada atualmente, então não podemos adicionar mais mapeamentos até que tenhamos algumas propriedades exclusivas nesta Se soltarmos isso, podemos definir isso como Ia underscore fire E então, se derrubarmos a categoria aqui, é aqui que podemos começar a fazer o mesmo tipo de mapeamento que vimos anteriormente. Então, se eu quiser que a funcionalidade de disparo seja chamada na barra de espaço, posso pressionar o botão aqui, pressionar barra de espaço e temos Se eu também quiser que ele reaja ao clique esquerdo do mouse, posso clicar aqui e clicar com o botão esquerdo do mouse. Também farei a mesma coisa última vez com o gamepad Vou pressionar o botão novamente e pressionar o botão frontal inferior, o botão A no gamepad, e temos esse limite Então, agora temos três botões diferentes ou três entradas diferentes, que podem chamar a função de disparo quando começamos a implementá-la Queremos fazer a mesma coisa novamente nossas outras ações de entrada. Então, vamos pressionar o sinal de mais. vincular algo ao reinício Isso vai ser bom e simples, então eu vou fazer isso primeiro. A mesma coisa novamente, poderíamos ter potencialmente R para reiniciar, e talvez eu também adicione um para o gamepad e faça dele o botão Iniciar Então esse é o botão especial do lado direito. Só para observar, estou usando a tecla Shift para a esquerda e pressionando as setas, que fará com que tudo volte ao normal Se você quiser alguns atalhos aqui, segure Shift, pressione o botão esquerdo e você pode ver que isso desdobra cada Portanto, uma boa maneira rápida de desdobrar ou desmoronar perfeitamente quando estamos passando mapeamento final que eu queria criar será o movimento. Então, vamos adicionar mais um desses. Vamos vincular isso a um movimento de sublinhado Vamos deixar isso lá embaixo. E, novamente, vamos querer adicionar algumas chaves aqui. Se começarmos da mesma forma que fizemos anteriormente, clicaremos no botão aqui, pressionaremos D para ter um movimento padrão para a direita e, em seguida, clicaremos em outro, pressionaremos A para obter nosso movimento para a esquerda. Agora é aqui que as coisas mudam um pouco, e isso é exclusivo das configurações de entrada aprimoradas. Embora os tenhamos definido como um eixo unidirecional, um valor de ponto flutuante para nosso movimento de sublinhado IA, você pode ver que na verdade não temos nenhum valor flutuante para alterar aqui para inverter nenhum valor flutuante para alterar aqui para o A e fazer as coisas se moverem para a esquerda Em vez disso, é aqui que entram os modificadores com o sistema de entrada aprimorado Então, se clicarmos no sinal de mais no modificador, podemos soltá-lo e você poderá ver várias funcionalidades úteis pré-integradas Podemos adicionar coisas como zonas mortas para manípulos analógicos, escalares automáticos e coisas assim, que podem ser aplicadas à entrada Aquele que queremos está aqui, então queremos negar o valor O padrão será um. Se negarmos isso Isso é o que nos dá um negativo. Tão agradável e simples de usar apenas uma abordagem um pouco diferente. Eu vou fazer a mesma coisa novamente. Eu só vou adicionar mais dois. Um para a seta direita. Um para a seta esquerda. Adicionaremos esse mesmo modificador na seta para a esquerda. E, finalmente, adicionarei uma entrada final por movimento e moverei o manípulo analógico esquerdo novamente. Agora, a mesma coisa acontece aqui. Não precisamos adicionar negativos aqui porque o Unreal sabe que um stick analógico tem um potencial esquerdo e um potencial direito no eixo x, ele retornará automaticamente um negativo quando eu pressioná-lo para a Isso é tudo configurado e pronto para ser usado no movimento de sublinhado do IMC Então, clicaremos em Salvar e podemos fechar este. Não precisaremos editar nada lá novamente. Então, isso pode ter parecido um pouco entediante. Como mencionei, ele tem uma configuração um pouco mais inicial, mas você só precisa configurá-la uma vez, e esses ativos podem ser copiados para dois outros projetos com muita facilidade se você descobrir que está usando padrões semelhantes E o principal é que, em projetos maiores, isso começará a economizar muito mais tempo, pois é muito mais flexível do que o sistema de entrada antigo. Agora queremos voltar para nossa aula de pornografia. Essa é outra em que eu realmente preciso que você se concentre, porque essa é a etapa que todo mundo geralmente esquece com o sistema de entrada aprimorado O contexto de mapeamento existe, mas nada o está usando ainda. E, diferentemente do sistema de entrada antigo, nosso sistema de entrada aprimorado precisa estar explicitamente vinculado a uma classe Podemos fazer isso com muita facilidade, e essa é a etapa que todo mundo muitas vezes esquece de fazer Desde o início do jogo, podemos clicar com o botão direito do mouse em algum lugar perto daqui e procuraremos a função integrada do controlador G player. O controlador do player é o que está recebendo a entrada diretamente de nossos dispositivos físicos, transformando-a em irreal e decidindo como gerenciá-la em toda a panela que ele possa estar Isso também pode se aplicar à IA, então essa seria a entrada que a IA está dando ao peão controlado pela IA Do controle, vamos retirar o pino aqui e procurar algo chamado subsistema de player local de entrada aprimorada G. Um nome muito bonito aí. este aqui com o F rosa, então isso indica que é uma função. Ele retornará apenas um determinado valor, que é aquela entrada aprimorada, o subsistema de player local E a partir daqui, essa é a função que realmente precisamos. Vamos chamar o contexto de mapeamento de anúncios. Bonito e claro. Podemos ver exatamente o que isso fará. Isso adicionará um contexto de mapeamento específico, aquele que acabamos de criar para ser vinculado à classe em que estamos atualmente. Então, vamos nos certificar de conectá-los ao pino de execução, colocar aqui o contexto de mapeamento que queremos usar, e só temos aquele em que temos o IMC underscore Man No entanto, a forma como você pode usar isso , como mencionei, é que você pode ter um controlador específico mais avançado, que monitora o que você pode estar fazendo durante o jogo . Durante os momentos de jogo, isso garantiria que o contexto de mapeamento estivesse usando o IMC do jogo, e você também pode ter algo como um IMC do menu principal , para poder navegar com o teclado no menu principal Quando o jogador pressiona pausar ou escapar, o controlador do jogador seria responsável por alterar o contexto de mapeamento para ir da jogabilidade ao menu E é aí que isso se torna muito, muito flexível. Como mencionei, é um pouco exagerado para o tipo de projeto que estamos criando, mas é útil saber, e você pode realmente aproveitar isso em qualquer um de seus projetos E o que eu realmente quero levar para casa novamente, essa etapa é fundamental. Já vi tantas pessoas configurarem tudo perfeitamente. Eles têm todas as informações configuradas. Toda a funcionalidade de movimento estaria funcionando corretamente. Eles apertam play e nada acontece. Você passa uma hora depurando e finalmente percebe que se esqueceu de vincular o esqueceu de vincular Portanto, não seja essa pessoa. Então, a última coisa que queremos fazer aqui é substituir a entrada antiga que tínhamos. Se clicarmos em Compilar, porque removemos a entrada antiga das configurações do projeto, isso é o que eu quis dizer : na verdade, receberemos um erro ou aviso muito útil aqui embaixo Agora está nos dizendo que está tentando referenciar algo que é um eixo desconhecido. Se pressionarmos esse texto sublinhado aqui, isso realmente nos levará direto para onde os problemas estão ocorrendo. Tão agradável e fácil. E tudo o que precisamos fazer é pegar esse nó que não existe mais nas configurações do projeto. Pressione delete. Podemos clicar com o botão direito do mouse aqui e queremos pesquisar nosso movimento de sublinhado de IA A mesma coisa, muito semelhante à entrada antiga. Temos duas opções. Obtemos os eventos de ação, que criariam um nó como esse, onde temos um pino de execução e a variável flutuante, ou podemos usar a ação do eixo aqui, o valor da ação A mesma coisa que o valor do eixo que tínhamos anteriormente. Então, vamos selecionar esse. Isso nos dará apenas o valor do ponto flutuante, e podemos conectá-lo novamente. Portanto, o código em si é praticamente idêntico. Nada realmente mudou. É assim que vamos configurar a entrada aprimorada para nos fornecer essas informações. Isso torna a transição relativamente perfeita, e toda a nossa lógica de movimento permanecerá exatamente a mesma Se apertarmos play, podemos testar isso. Então A e D estão fazendo a mesma coisa, esquerda e direita, e esse é o manípulo analógico novamente. Então, tudo funcionando exatamente como esperávamos. Tudo o que precisamos fazer é atualizar a camada de entrada abaixo do nosso código principal . E é isso. Agora temos o sistema de entrada aprimorado em nosso projeto, totalmente configurado, que exigiu um pouco mais do que a configuração de entrada antiga, mas é muito mais flexível e definitivamente vale a pena Posteriormente, usaremos mais recursos, como eventos de incêndio para fotografar, acionar entradas retidas em um loop e, em seguida, também o único botão de reinicialização de disparo O próximo tópico que queremos abordar, porém, serão nossos limites de jogabilidade. No momento, podemos voar até a afinidade, que não é muito bom para qualquer disparo E, claro, se você quiser experimentar, pode tentar adicionar coisas como modificadores de zona morta para a entrada do manípulo, ver como temporizadores ou pulsos podem funcionar usando Nenhum código é necessário e apenas algo com que brincar. 9. 08 — Limites: Novo sistema de entrada, ainda temos esse problema em que atualmente podemos voar para o infinito. Eventualmente, você enfrentaria algum tipo de problema de precisão de ponto flutuante, mas muito antes disso, o jogo se tornaria jogar e, o mais importante, muito chato Para esse tipo de jogo, vamos querer uma câmera fixa e algumas paredes delimitadoras, algumas paredes invisíveis A câmera que temos atualmente está acoplada ao peão e, para fotografá-lo, uma câmera nivelada faria mais sentido Então, se voltarmos para a base do painel de sublinhado da BP, podemos pegar a seleção de controle do braço de mola, a câmera, e simplesmente excluí-las Se apertarmos play, agora estamos de volta dentro da nave, então recuperamos o problema, mas estamos prestes a corrigi-lo imediatamente. O principal é que agora você conhece a estrutura de jogo e sabe por que estamos examinando o interior de nossa nave. Caso contrário, volte alguns tópicos. Se voltarmos ao nível principal, queremos apenas adicionar uma câmera. No topo, logo acima do mirante, há um pequeno cubo, que é nosso botão de adição Se colocarmos isso abaixo, queremos procurar a câmera opcional. Muitas das opções aqui tendem a mudar categoria a cada poucas versões irreais, então a pesquisa pode ser um pouco mais rápida porque a vida é muito curta para procurar câmeras Um que queremos é nosso ator de câmera. Isso será lançado diretamente no mundo se selecionarmos isso. A câmera precisará ver onde o jogador aparecerá, e já sabemos novamente, pela estrutura de jogabilidade, como estamos gerenciando isso e onde isso acontecerá Então, um bom atalho rápido aqui para você. Se você pegar o início do jogador, que é onde o jogador aparece, iremos ao painel de detalhes no lado direito, clicaremos com o botão direito na propriedade da localização e poderemos copiar a localização real do início do jogador Se pegarmos a câmera, faremos a mesma coisa, mas clicaremos com o botão direito do mouse aqui e colaremos a propriedade que acabamos de fornecer. Então, agora temos a câmera diretamente no ponto de partida do jogador. Também queremos dar alguma rotação a isso. Então, dentro do visor, podemos pressionar F para focar na câmera Se quiser, você pode entrar no modo de rotação e usar os widgets aqui Agora eu sei que, para nossas necessidades, queremos apenas girar a câmera -90 graus no eixo Y. Então, vou fazer isso no painel de detalhes, e agora estamos olhando diretamente para o chão. Isso pode estar um pouco perto demais. Então, a próxima coisa que vamos querer fazer é mover a câmera para cima no eixo Z. Então, novamente, se pegarmos o valor Z aqui, colocarei um valor de 2.400 Acho que isso é semelhante ao que tínhamos anteriormente. Agora podemos ver que vamos olhar diretamente para a largada do jogador e para onde o avião vai desovar. Talvez você não fique tentado a pressionar play e ver o que acontece A razão é simples se tivéssemos cinco, sete, 20 câmeras na cena? Como ele saberia qual escolher? Como com as outras regras que estamos definindo, queremos controlar isso e definir isso manualmente. Então, com o ator da câmera selecionado, queremos apenas pesquisar neste painel aqui, no painel de detalhes, queremos pesquisar algo chamado ativação do Autoplayer Podemos ver que temos essa opção aqui. A ativação automática para o jogador está atualmente configurada para desativar. Se colocarmos essa opção e selecionarmos o jogador zero, esse será o primeiro e único jogador em nosso jogo para um jogador. Então, agora a estrutura sabe usar a câmera que acabamos de selecionar. Se apertarmos play, podemos ver isso. Precisaremos fazer alguns ajustes para centralizar tudo corretamente, mas agora estamos analisando aproximadamente onde queremos estar Então, com o posicionamento da câmera, queremos que o jogador fique mais próximo da parte inferior da tela, como invasores do espaço e, novamente, recrie um pouco a configuração nos exemplos de conteúdo que estamos usando O problema com o editor e a usabilidade aqui é que o início do player não tem nenhuma visualização Portanto, será um pouco difícil ver onde a nave do jogador realmente surgirá e posicionar a câmera adequadamente Então, um truque rápido que eu queria apresentar podemos adicionar uma esfera ou forma temporária, algo parecido com isso, para mostrar onde o jogador começa. Se formos até o botão Adicionar aqui em cima, podemos acessar nossa opção de formas. Sei que ainda tenho a localização armazenada desde o início do player mais cedo, quando a copiei Vou desfazer a busca pelo Autoplayer aqui, clicar com o botão direito do mouse e colar a localização do player E eu olho para essa esfera, que está diretamente no início do jogador. Se pegarmos o ator da câmera novamente, isso ajudou porque agora podemos ver exatamente o que a câmera estará olhando. Pressionando F, eu volto a olhar exatamente para a câmera e podemos arrastá-la até o lugar certo Então, se levarmos a câmera para frente ou pudermos fazer com que os jogadores avancem, qualquer uma delas ficará perfeitamente bem. O principal é que queremos que a nave do jogador esteja mais ou menos aqui embaixo. Então, essa é uma maneira agradável e fácil de colocar as coisas em posição de forma agradável e rápida. Se eu pegar a esfera, posso deletar isso. Obviamente, não queremos que isso fique no laboratório. Podemos pressionar play e colocar os jogadores mais perto de onde queríamos que estivessem. Outra dica da câmera que eu só queria mostrar muito rapidamente é se pegarmos a câmera novamente, enquanto você está brincando com as coisas. Se você não quiser que essa janela de demonstração seja desativada automaticamente ao selecionar outra coisa, podemos escolher este pequeno ícone de alfinete aqui embaixo, que fixará essa janela no seu visor Então, se você precisar entrar, mova os jogadores para algo ao redor para ver o que está acontecendo pela visão da câmera, outra dica rápida de que podemos manter isso na tela temporariamente. Quando você quiser que isso desapareça, basta pressionar o pino novamente e ele se soltará da janela de exibição Apenas algumas coisas para começar a se familiarizar e se familiarizar. Vou pegar outra forma aqui. Acho que já mencionei isso algumas vezes, mas se você pressionar F com um objeto selecionado, estará focando no objeto que deseja olhar. Você pode clicar para girar diretamente ao redor do objeto. E outra coisa que pode ser bastante útil é que, se estivermos colocando algo assim, podemos segurar uma tecla Shift, clicar com o botão esquerdo na direção do widget e arrastá-la Então, se começarmos a arrastar um objeto aqui e depois pressionarmos Shift, se ele estiver se movendo, podemos realmente fazer com que a câmera no visor continue rastreando o objeto que estamos Muito útil se você está tentando reproduzir alguma coisa e não quer continuar movendo-a, movendo a câmera, movendo-a novamente e assim por diante Então, apenas algumas dicas rápidas para se familiarizar com o visor. Agora vamos querer começar a analisar os limites. Mais uma vez, no botão Adicionar, procuraremos algo aqui chamado volume de bloqueio. Podemos ver como temos a opção de bloquear o volume. Vamos selecionar esse , e o que nos é dado é esse cubo invisível Isso representará nossa parede invisível, e só queremos colocá-la em todo o nível para bloquear onde o jogador ou os inimigos possam bater. Para colocar isso em prática, vou fazer a mesma coisa novamente. Vou clicar com o botão direito do mouse e colar o local de início do player . Isso nos colocará aqui. Para este, podemos colocá-lo no lado esquerdo da nossa zona de jogo, que eu sei que, por meio de testes, seria um bom ponto de 1.240 negativos Isso colocará isso um pouco acima. Pronto perfeitamente no eixo Z. Isso é alto o suficiente para que o avião realmente colida com isso Se colocarmos isso na posição X de zero, isso colocará esse tipo de meio nível no eixo Ford. E então o que queremos fazer aqui é dimensionar a caixa para cobrir toda a extensão. Agora, uma maneira de fazer isso é tornar o eixo X aqui muito mais longo. Isso mudará a caixa. Isso é meio que esticar o ator real. Quando estamos trabalhando com coisas como volumes, temos outra opção. Então, vou voltar para a maneira ideal de trabalharmos com eles alterando as configurações do pincel aqui. Então esse é o tamanho da caixa que temos atualmente, que tem 200 centímetros de diâmetro. Então, se definirmos isso para algo muito maior, adicionarei alguns zeros aqui Então, teremos uma caixa de 20.000 unidades apenas para garantir que estamos encapsulando toda a zona de jogo e um pouco mais, provavelmente Mas está perfeitamente bem. A razão pela qual queremos fazer isso é porque isso está alterando a escala do componente real interno, esse componente da caixa de pincéis. Já esse valor aqui em cima é a escala de todo o ator real. Então, se conseguirmos manter esse uniforme e limpo ao mesmo tempo, se alguma vez precisarmos verificar as coisas no código, será um pouco mais fácil trabalhar com ele. E, novamente, apenas mantém nossa estrutura um pouco mais organizada. Enquanto estivermos aqui, vou deixar a altura um pouco maior Então, talvez queiramos definir isso para algo como 1.000 no Z apenas para ter certeza de que estamos definitivamente bloqueando absolutamente tudo. Outra coisa que pode ficar um pouco confusa é que, se for um pouco difícil de ver, temos opções para alterar a opacidade, podemos adicionar um volume sombreado na tela e começar a ver onde está o Novamente, isso não aparece no modo de jogo, mas aparece pela câmera, o que torna um pouco mais fácil de ver. E o principal é poder avaliar onde o volume de bloqueio realmente ocorrerá Feito isso, vou pressionar Control em D depois de selecionar o volume de bloqueio que configuramos. Vou definir isso para 1.240, então temos isso no lado direito do campo de jogo Então, o YX está aqui. E só para torná-lo visível, como no lado esquerdo, vou rolar de volta para baixo. Ative o volume sombreado da tela e os dois terão a mesma aparência . Esteja ciente também. Acho que quando duplicamos as coisas, Unreal tenta mover o ator duplicado em várias unidades qualquer maneira para que elas não Então você pode ver que no volume do lado direito, temos alguns deslocamentos no X. Isso na verdade não causaria nenhum problema Mas só para acalmar as vozes e meu cérebro, vou colocar isso de volta em zero e tudo de novo, bem arrumado e bem Com várias alterações como essa feitas, talvez você queira pressionar Control Shift e S para salvar tudo em que estamos trabalhando. Então, agora podemos entrar no playode. Vamos olhar pela nossa câmera. Vai ser um pouco difícil de ver porque não podemos ver o volume real de colagem aqui Então, se quiséssemos testar coisas e ter certeza que sabemos exatamente quando poderíamos estar atravessando uma parede, outra opção, um pouco demorada aqui, é que poderíamos voltar às formas. Poderíamos adicionar um cubo Deseja acessar as configurações de colisão no painel de detalhes no lado direito e, apenas para garantir que verificaremos apenas nosso volume de bloqueio, podemos selecionar a predefinição de colisão aqui e transformá-la aqui e transformá-la Examinaremos mais sobre a colisão um pouco mais tarde, mas isso é apenas para obter algo visual Então, novamente, vou voltar aos detalhes, colar isso no local e colocar -1.240 Para maior rapidez e simplicidade, vou mantê-lo aproximadamente do mesmo tamanho. Não precisa ser exato, então vamos pegar o cubo No eixo Y, precisamos fazer essas duas unidades no Y para obter aproximadamente o tamanho do nosso volume de bloqueio e, novamente, vamos torná-lo muito maior no X para que ele abranja tudo e maior novamente no Z. Não precisamos ser tão cuidadosos Aqui. O principal é que é apenas algo visual para que possamos ver se e quando o jogador estaria atravessando a parede, para que possamos ver isso aqui. O principal motivo é que eu sabia que a colisão não funcionaria e só queria eliminar imediatamente o fato de que estamos realmente passando pela área de ligação, que deveria estar colidindo conosco O motivo pelo qual eu queria apresentar isso, pois sabia que isso iria acontecer, nos dá um pequeno exemplo de como podemos fazer a depuração Isso é muito importante no desenvolvimento, na verdade, entender como resolver problemas, resolver as coisas e descobrir o que está acontecendo. Já meio que resolvi um dos problemas. A primeira coisa é que não saberíamos se estivéssemos apenas voando se realmente atravessamos a parede ou não. Então, já descartamos o fato de não estarmos alcançando a parede Podemos chegar ao ponto da parede e ir mais longe e nenhuma colisão está acontecendo Então essa é uma opção da lista de verificação completamente preenchida. Se eu pegar o volume de bloqueio à esquerda aqui, tentaremos corrigir esse primeiro. O primeiro suspeito pode ser as propriedades de colisão que acabei de mostrar a você Então, no lado direito do painel de detalhes, voltaremos às propriedades da colisão Em caso de colisão, podemos ver que essa predefinição está configurada para parede invisível Se deixarmos isso de lado, podemos dar uma olhada no que isso significa. E esta será uma breve visão geral da colisão. Novamente, haverá muito mais profundidade sobre isso em tópicos futuros. Mas, por enquanto, tudo o que precisamos saber é que temos três tipos diferentes. Temos Ignorar, sobrepor e bloquear. Ignorar faz o que você pensa. Ele ignora todos os outros aceleradores e interações. Overlap é procurar duas coisas que estão no mesmo espaço físico, mas que não se tocam fisicamente com coisas como física e se bloqueiam E então temos o bloco, que seria dois objetos físicos se impactando e tentando se afastar para que não habitassem o mesmo espaço físico Resumindo, a parede invisível é configurada exatamente como queremos. Está configurado para bloquear absolutamente tudo no mundo. A propósito, esse é o nosso segundo suspeito. Sabemos que estamos alcançando a parede e sabemos que a parede está colidindo. A próxima coisa é que vamos analisar a colisão das panelas Então, se vamos para a classe de peões, vamos para a malha estática, e a colisão no momento está sendo tratada na Então, no painel de detalhes, novamente, vamos querer rolar para baixo e encontrar a colisão Apresentaremos as predefinições de colisão e podemos ver que isso está configurado para bloquear todas as Agora, isso realmente não importa. Novamente, o importante dessas caixas de seleção aqui. Isso também está marcado para bloquear absolutamente tudo. E se voltarmos ao mundo muito rapidamente, teremos um curso intensivo de colisão aqui, podemos ver que a parede invisível está configurada para ser seu tipo de objeto e configurada como estática mundial A pornografia em si é definida como dinâmica mundial. Então, isso está tentando bloquear objetos estáticos do mundo, e isso está procurando bloquear objetos dinâmicos do mundo. Então, enquanto esses dois quiserem interagir, devemos ver algum bloqueio físico. A propósito, esse é o terceiro suspeito. A colisão de pornografia está, na verdade, configurada corretamente. E isso realmente deixa a única coisa: provavelmente fizemos algo errado em nosso código. E alerta de spoiler, eu já sei que esse é o problema. Então, se entrarmos no gráfico de eventos do evento, passaremos para nossa função de localização do ator definido aqui. E essa é uma daquelas coisas em que seria muito difícil depurar e realmente saber que esse é o problema sem realmente ter experimentado isso Duas coisas a serem observadas aqui são os booleanos de varredura e teletransporte na chamada Se passarmos o mouse sobre a varredura, podemos ver aqui que a descrição que obtemos é se varremos o local de destino acionando podemos ver aqui que a descrição que obtemos é se varremos o local de destino acionando sobreposições ao longo do caminho. Isso é muito importante. Também controlamos se paramos perto do alvo se algo for bloqueado por alguma coisa. A parte realmente importante aqui é que, se não tivermos essa opção ativada , não verificaremos nossa posição está bloqueada, o que significa que não acertaremos nada Resumindo, desmarcar a varredura é, tecnicamente, meio nos teletransportar para o local em que queremos Então, se marcarmos isso, clicarmos em compilar e salvar, voltaremos e testaremos novamente. Agora podemos ver que quando estamos sobrevoando, agora estamos sendo bloqueados. Portanto, não precisamos alterar nenhuma das predefinições de colisão Falaremos sobre eles um pouco mais tarde. Isso significa, também, que a parede do lado direito funcionará porque está configurada exatamente da mesma maneira, então está perfeitamente bem. Era uma coisa muito simples, muito fácil de ignorar em nosso código Então, eu queria incluir isso só porque, como mencionei, as coisas nem sempre correm perfeitamente, e você precisa se sentir confortável depurar e tentar resolver as coisas que você logicamente acha que poderiam ser parte Essa é uma daquelas coisas que acaba sendo uma pegadinha muito comum É muito fácil perder. É muito difícil de depurar se você não sabe o que está procurando Mas se isso tivesse falhado, até mesmo eu , como desenvolvedor experiente, eu estaria meio que fora dos possíveis caminhos de pensamento que eu poderia ter percorrido, e teria que ter simplesmente acessado Google, o RDI ou algo parecido e tentado descobrir se alguém tivesse um problema semelhante Então, basta uma rápida limpeza dos limites agora. Eu vou voltar para dentro. Vou me livrar desse cubo branco aqui. Isso foi só para visualização Agora sabemos que estamos desovando no lugar certo e estamos sendo bloqueados pelas duas paredes aqui. Então, com isso feito. A câmera está fixa. Agora está no lugar onde queremos. Os limites estão definidos e, quando começarmos a adicionar inimigos, eles detectarão as paredes e saltarão entre elas. Obviamente, depois de implementarmos esse código. Antes disso, porém, vamos começar a analisar os materiais, os mais tipos de elementos visuais do nosso projeto. Poderemos personalizar a aparência de nossas naves para que todos os inimigos não pareçam idênticos ao jogador. Como sempre, se você quiser experimentar, no momento, tente algo simples. Tente adicionar um limite superior e inferior, especialmente se você já tiver algum movimento para frente e para trás Mais uma vez, mesmo processo, eixos diferentes, só para você se familiarizar e experimentar coisas diferentes 10. 09 — Instâncias de materiais: No momento, se começarmos a criar nossos inimigos, eles se parecerão exatamente com o nosso jogador. Mesmo avião azul, não há como realmente diferenciá-los. É por isso que nossos materiais chegam, permitindo que envolvamos cores e imagens diferentes em nossos três modelos D para diferenciá-los e adicionar alguma variedade Não criaremos materiais do zero, pois essa seria sua própria toca de coelho E, como mencionei, estamos focados principalmente em programação, práticas e projetos, os três Ps. Mas vou mostrar como podemos criar variações de cores a partir do que eu realmente forneci. Embora não criemos novos materiais do zero, quero mostrar a vocês os materiais que já temos. Se examinarmos os materiais da pasta de ativos, conforme mencionei anteriormente com as convenções de nomenclatura, temos algumas coisas aqui para analisar Temos dois sublinhados MM na água e na textura, e temos quatro sublinhados MI, que são as instâncias materiais Mm, que é um prefixo para material mestre. É aqui que a lógica real do sombreador acontece. Abrimos a base da textura, não editaremos nada aqui, mas eu só queria mostrar a vocês algumas terminologias e detalhes com os quais você deve se familiarizar Se passarmos para o lado esquerdo do gráfico aqui, isso é muito parecido com o gráfico de planta que podemos clicar com o botão direito do mouse e arrastar para mover A principal coisa que temos são três entradas de amostra de textura Temos a cor base, que é nosso mapa de cores, os azuis, o grão da madeira, a tinta E tudo isso foi retirado do mapa Ubi no modelo de três D. Em seguida, temos nossa textura normal ou o mapa normal, que adiciona detalhes da superfície sem geometria, aquelas saliências, nervuras, linhas de painel e assim por diante, tudo falsificado ao manipular a forma como A última coisa importante é a textura do ORM. Nesse caso, isso é algo que eu criei pessoalmente e tenho um fluxo de trabalho um pouco diferente. Eu criei isso como um ORME especificamente desta vez. São essencialmente quatro imagens em tons de cinza agrupadas em um único arquivo de textura, canais RGBA A principal razão para isso é que todos os dados contidos neles podem ser extrapolados em escala de Isso economiza memória e é um pouco mais fácil de trabalhar. Nesse caso, o canal vermelho é a oclusão do ambiente. É aqui que a luz terá dificuldade em alcançar. O canal verde é rugoso, criando uma superfície espelhada lisa versus fosca em O canal azul é metálico. Isso é binário. Isso é metálico ou não metálico, e o canal Alpha é emissivo, mostrando quais partes Algo que é útil observar ao trabalhar com materiais é que, em vez de apenas ter essa representação esférica aqui, podemos alterar o que aparece neste visor com um truque útil Se abrirmos o desenho de conteúdo e entrarmos na pasta de malhas, pegue uma malha que você gostaria de visualizar com seu Nesse caso, será o herói comum. Não precisamos fazer nada com isso. Só precisamos que isso seja selecionado. Podemos voltar ao material e até lembrar o que selecionamos atualmente dentro da gaveta de conteúdo Pode mudar a representação, a visualização do nosso material aqui para ser coisas como um cilindro, um plano, um cubo E então, especificamente, esse ícone de tijolo aqui. Se você tiver uma malha estática selecionada e clicarmos nela, ela nos dará uma representação, visualização do nosso plano ou da malha que atualmente selecionamos no desenho do conteúdo Portanto, isso pode ser muito útil para visualizar as coisas e ver exatamente o que é responsável Mas e quando você está alterando propriedades diferentes e recebendo esse feedback imediato? Em seguida, quero que você se concentre nesses nós nomeados em todos os lugares. Eles são chamados de nós de reraiz nomeados. Em vez de fios se estendendo por nosso gráfico, algo como um quadro de evidências de teoria da conspiração. Em vez disso, podemos escolher criar conexões nomeadas apenas uma vez e, em seguida, podemos referenciá-las em qualquer lugar dentro do nosso Shader. Completamente opcional. Você nem sempre os verá usados em outros exemplos, mas, novamente, permite que eu mantenha toda a minha lógica de Shader no lado esquerdo e depois chame as coisas quando eu precisar delas no lado direito Uma daquelas coisas em que a ferramenta existe, então por que não usá-la Como mencionei, porém, eu não recomendaria alterar nada dentro do material principal , a menos que você saiba o que está fazendo ou, pelo menos, faça uma cópia e faça alguns ajustes nela para que você sempre tenha algo em que recorrer O principal motivo é que o próximo tópico que examinaremos são as instâncias materiais e a forma como a instância funciona é direcionar as informações diretamente desse material principal. Então, se algo ocorrer aqui, você potencialmente quebrará todas as instâncias que dependem disso. Então, de volta à pasta de materiais, se você se mudou, para economizar um pouco de tempo, podemos usar um ponto de partida bastante lógico. Já temos um avião. Ele tem a maioria das texturas e tudo configurado exatamente como precisamos, e esse é o reprodutor de avião MI underscore Então vá em frente e pegue este, pressione control, na verdade, para duplicar e renomear este para avião inimigo, mantendo o MI na Se clicarmos duas vezes e abrirmos isso, agora podemos começar a analisar instâncias materiais. Podemos ver que isso é muito diferente do nosso material principal. Uma coisa para ficar de olho aqui está no lado direito do painel de detalhes. Algo que devo mencionar, você provavelmente está percebendo padrões aqui Toda vez que estamos em um painel, sejam materiais, plantas, componentes, vasos de visualização, quando você pega algo, normalmente há um painel de detalhes em algum lugar para fornecer informações sobre o que você está vendo, que é definitivamente uma das coisas boas do Unreal Quando você começa a aprender partes dos conjuntos de recursos, isso é transferido para diferentes recursos dentro do mecanismo. Mas o que eu estava prestes a dizer é se olharmos para o painel de detalhes, temos o pai sendo indicado aqui, e isso mostra que essa é da textura de sublinhado MM. Então, podemos clicar duas vezes nisso, e isso nos leva de volta ao material que acabei de mostrar a vocês. Então, como mencionei, todas as informações vêm diretamente desse material principal. Outra coisa, seria bom visualizar o avião novamente. Então, só para recapitular, volte para a pasta de malhas, pegue o avião e pressione o ícone de tijolo aqui dentro da instância do material As principais coisas que queremos mudar são as texturas. Podemos ver que isso é muito diferente. Não temos nenhuma informação do gráfico ou desse sombreador aqui Tudo isso é usado especificamente no material principal. Dentro da instância, o que temos, em vez disso são coisas que eu escolhi especificamente expor Tudo isso com nomes de notas grandes aqui, as texturas, a cor da textura Essas são variáveis parametrizadas que eu expus para que possamos vê-las na instância Então, o que queremos observar se abandonarmos as categorias de Dan é essas são todas as coisas que acabei de mostrar: as propriedades expostas. Ao expor essas instâncias internas, obtemos um ambiente de trabalho muito agradável, onde podemos simplesmente fazer uma alteração e ver essa atualização imediatamente Então, podemos fazer isso para obter nosso primeiro tipo de inimigo. Se colocarmos essa cor base de textura, então as informações de cor, vamos procurar o inimigo verde. Acho que vou deixar os inimigos verdes. Eu forneci várias cores de textura diferentes aqui se você quiser expandir isso e criar seus próprios tipos de inimigos. Acho que incluí amarelo, roxo, talvez laranja ou vermelho. Vou escolher a textura da cor base verde, e podemos ver que isso mudará imediatamente nossas informações sobre a planície. A maioria das texturas normais e OIME provavelmente são praticamente as mesmas, mas eu as exportei individualmente por textura quando as criei Então, podemos muito bem seguir em frente e pegar o normal. Então, vamos procurar o verde novamente e vamos encontrar o herói verde puro. Mas desta vez, queremos a textura normal. E, finalmente, vamos reduzir o espaço OIME e procurar o verde novamente, e vamos substituí-lo pelo verde herói OI ME Ok. Então, só para ter certeza de que estão exatamente com os modelos que fiz dentro do liquidificador, caso alguém estivesse curioso, alinhados exatamente com os modelos que fiz dentro do liquidificador, caso alguém estivesse curioso, eu os texturizei e coloquei todas essas informações no Substance Então, como mencionei, você pode ver fluxos de trabalho semelhantes, mas ligeiramente diferentes Tudo se resume ao artista e à pessoa que os está fazendo. A principal coisa a observar, porém, é que recebemos esse feedback imediato. Assim que mudamos alguma coisa, não há recompilação, vimos a nova textura aplicada ao material, o que é um dos principais benefícios das instâncias do material Definitivamente, não é exclusivo desse benefício, e devemos sempre tentar usar instâncias materiais sempre que possível, em que as coisas compartilhem propriedades, características e valores semelhantes que podemos expor Portanto, além das texturas, esse seria um ponto final perfeito se você estiver satisfeito com a aparência que está Eu só queria fornecer um pouco mais de informações sobre instâncias materiais, o que elas fazem e como podemos usá-las. Então, algumas das outras propriedades que eu expus aqui são valores de ponto flutuante ou cores que podemos alterar e substituir diretamente a cor geral ou a tonalidade que está sendo aplicada ao material ou coisas como o quão especular é o Portanto, a especularidade é muito fácil de ver. Se eu marcar a especularidade aqui, isso nos permitirá editar isso E, no momento, estamos em 0,5, especularidade aproximadamente média Essa é a quantidade de luz refletida de uma superfície, fazendo com que as coisas pareçam um pouco mais plásticas ou mais parecidas com borracha quanto maior a especularidade parecidas com borracha quanto maior a especularidade Geralmente, não temos nada com o qual interagimos diariamente que tenha zero especularidade Portanto, começar em torno 0,3 ou 0,5 é algo realista. Se reduzirmos isso para zero, obteremos esse feedback imediato. Quer dizer, eu tenho uma superfície completamente emaranhada e completamente não refletiva. Se colocarmos tudo isso em um, então a luz está voltando muito, muito mais Então, novamente, você pode ajustar recursos como esse e tentar ter uma ideia de como você gostaria que o seu fosse Você também pode brincar com coisas como uma máscara colorida ou uma tonalidade colorida Então, se usarmos a máscara de cor aqui, essencialmente uma porcentagem normalizada de 0 Portanto, zero é sem mascaramento e um é mascaramento total. Se ativarmos a cor da textura, esses dois funcionarão juntos. Portanto, a máscara de cor está mascarando a substituição da cor da textura Se eu tornar isso algo realmente óbvio, como uma cor vermelha, e depois desligar a máscara, tornando-a 100% eficaz, permitindo que 100% da cor apareça. Então, ele muda para o valor um. Agora temos um avião totalmente rosa. Portanto, podemos controlar isso com muita facilidade. E o melhor de tudo isso é que recebemos esse feedback imediato e a atualização imediata quando estamos fazendo essas alterações. Se você quiser que isso seja um pouco mais sutil, poderíamos mudar a máscara de cor para algo como 0,5, e estamos permitindo que apenas metade dessa cor apareça. Reduza para 0,2 e obteremos apenas uma tonalidade azul muito clara no topo do nosso plano verde Reduza tudo para zero, e não teremos nenhuma cor aparecendo. Então, outra coisa com a qual você pode jogar, junto com as diferentes texturas que você pode usar, e então as propriedades emissivas funcionam da mesma maneira Agora, eu não tinha nada aqui para realmente fazer brilhar, como faróis ou algo parecido Portanto, a emissão era mais uma forma de fornecer propriedades diferentes com as quais brincar. Se eu ativar a intensidade emissiva, precisamos dar a isso um valor maior que zero E então, se ativarmos a cor emissiva, no momento, ela é preta Agora, obviamente, preto é apenas zero, zero, zero no valor RGB Então, se multiplicarmos o preto por um ou 100, ainda teremos preto, o que não é nada Então, precisamos dar uma cor a isso se mudarmos isso para algo como amarelo ou laranja, e talvez precisemos aumentar a força um pouco mais. Na verdade, essa é uma daquelas coisas em que, ao explorar diferentes texturas, algumas delas, percebi que não precisaria de um canal emissivo repleto de texturas Então, se você quiser contornar a propriedade emissiva, pode entrar na textura OME aqui e mudaremos isso para o plano azul novamente. aviões aqui são azuis. Teremos que diminuir o tom disso um pouco. Talvez, mas há algo mais parecido com um ou 0,5, então não está substituindo completamente a cor E você pode fazer o avião inteiro brilhar um pouco aqui. Portanto, você também tem controle sobre a propriedade emissiva Como eu disse, infelizmente, não pensei em modelar alguns faróis com antecedência, mas queria aprimorar as propriedades emissivas para que você pudesse fazer o você pudesse fazer avião inteiro brilhar e se divertir Pode ser útil se você quiser animá-lo explodindo ou Você pode fazer com que ela brilhe entre sua cor normal e, tipo, um vermelho antes da explosão acontecer, uma ideia Só para ajudar a visualizar o que está acontecendo aqui e como essas texturas, especialmente o OIME, especialmente o OIME Eu sei que isso pode ser muito confuso. Vou apenas desligar isso e atrasá-los porque não quero substituir nenhum deles E vou transformar a textura novamente em verde para o OIME, como eu sei, que foi cozido especificamente para essa propriedade de cor Eu só queria mostrar rapidamente as texturas e o que está acontecendo Então, quando digo que eles foram incorporados em canais diferentes, se entrarmos na pasta de texturas, descobriremos que realmente não importa qual deles, para ser honesto. Podemos simplesmente encontrar o herói azul claro e eu vou abrir o canal OIME Então, normalmente, na maioria das texturas, as cores e tudo o que estamos vendo aqui vem dos canais RGBA, todos combinados ao mesmo tempo Se você tirar um pouco, tudo o que você vai acabar com são cores meio turvas e estranhas como essa, onde vermelho e azul somados obviamente nos darão Vermelho e verde nos darão uma espécie de cor laranja e assim por diante. Então, não o usaríamos dessa forma. Com o processo ORME, é um pouco diferente. E isso é porque o que eu fiz, no canal vermelho, é nossa oclusão ambiental Portanto, qualquer coisa que seja branca essencialmente não bloqueada por nenhum outro elemento do modelo. Então, a luz está nos impactando totalmente, e então qualquer coisa que vá para cinza ou preto tem algum tipo de oclusão de outra parte do modelo, como o rolamento da roda íntima e coisas assim E aplicará um pouco de sombreamento falso para enfatizar as sombras No canal verde, essa era a nossa aspereza. Então, novamente, indo de um valor essencialmente de zero a um, áreas diferentes parecem ser mais aproximadas essas áreas aqui fornecem algum tipo de detalhe aproximado, enquanto elas serão muito mais suaves. O azul era o metálico, então, novamente, era metálico ou não Então, essa seria a frente da hélice. Existem algumas pequenas peças de metal nas rodas e outras pequenas características como essas. E então o canal Alpha foi incorporado e, como você pode ver aqui, isso é essencialmente o corpo inteiro do avião que foi incorporado ao canal emissivo Então, retirando essas informações e multiplicando-as nossas propriedades de cor e coisas assim no material, podemos manipular elementos específicos modelo por meio de nossos canais Portanto, é uma maneira inteligente de fazer as coisas. Isso economiza memória e nos dá um pouco mais de flexibilidade em nossos materiais. Apenas algumas outras coisas antes de encerrar esse tópico Se você quiser brincar com mais materiais, apenas para mostrar algumas maneiras diferentes de criar diferentes instâncias de materiais. Eu mostrei como duplicar nosso material original do player O controle em D duplicará isso. Se você sabe que só quer criar algo completamente novo, um material totalmente novo para brincar com eles, basta acessar o material e selecioná-lo. Se você já tem um material mestre com o qual trabalhar e deseja criar uma nova instância, clique com o botão direito do mouse no material mestre aqui, navegue até o topo aqui e crie uma nova instância de material. Isso lhe daria algo muito semelhante ao avião do jogador ou qualquer outra coisa que eu tinha anteriormente, e teria apenas alguns valores pré-preenchidos padrão, essencialmente o mesmo resultado. Então eu vou me livrar desse. Não vou precisar guardar isso. Só queria mostrar como você pode trabalhar com eles. Dizendo isso porque provavelmente é um dos tópicos mais fáceis de abordar, e não vamos nos aprofundar muito mais do que temos aqui. Definitivamente, recomendo dedicar algum tempo entre os tópicos para pausar os vídeos e dar um passo atrás Talvez crie algumas instâncias de material com cores diferentes. isso lhe daria a opção Posteriormente, isso lhe daria a opção de ter um inimigo verde, um inimigo roxo, um inimigo vermelho, o que se adequar à sua visão do jogo. Você também pode tentar dar chips diferentes, valores de secularidade diferentes, adicionar um pouco de propriedade missiva a alguns deles ou dar-lhes uma tonalidade de ou dar-lhes uma Então, se você realmente quiser começar a aprender mais sobre o motor e realmente entender o que está acontecendo, considere isso como uma pequena lição de casa entre este tópico e o próximo e tente criar alguns exemplos materiais entre eles Mas feito isso, esse é o nosso material meio que coberto, e estamos prontos para usar um material inimigo que possamos começar a criar nossas novas classes. Usando instâncias de materiais, conseguimos criar essa nova variação sem tocar em nenhuma camada, usando a única classe de material principal que eu forneci, com toda uma gama de possibilidades para que ocorram instâncias de materiais 11. 10 — EnemyMovement: hora de criar alguns inimigos. Aviso justo, primeiro faremos isso da maneira abaixo do ideal Você pode questionar algumas das opções se souber o que é irreal Mais uma vez, isso é totalmente intencional e, desta vez, é para nos permitir refatorar nosso trabalho A refatoração faz parte de qualquer desenvolvimento real. É pegar a base de código ou projeto que você já tem, melhorar o código que está funcionando e que você deseja manter e remover o que não precisa. Quero ter certeza de que terei a chance de passar por isso com você para que eu possa mostrar como tornar o processo um pouco mais indolor Mas é claro que, primeiro, precisaremos de algo que nos permita refatorar Para fazer isso, vamos criar nosso peão inimigo. Então, se navegarmos até a gaveta de conteúdo dentro do blueprint e da pasta principal, clicaremos com o botão direito do mouse aqui e acessaremos a opção de classe blueprint e criaremos uma nova classe Vamos dar a este o nome de BP Underscore pawn Enemy. Entre para abrir isso, e isso será quase idêntico ao que já configuramos para nosso player. E isso é essencialmente parte do problema inicial aqui. Vamos duplicar vários trabalhos que já fizemos Posteriormente, abordaremos a melhor solução, mas, por enquanto, vamos aproveitar o que tínhamos antes com nosso jogador. Então, no painel de componentes, sabemos que queremos adicionar uma nova malha estática. Vamos pegar nossa malha estática e colocá-la na raiz da cena padrão. Com a malha estática selecionada, vamos para o lado direito no painel Detalhes e optaremos por usar o herói do plano de sublinhado SM Claro, não queremos que seja da mesma cor. E se você não consegue ver seus materiais no painel de detalhes no momento, basta clicar na malha estática e encontrar o outro componente. Selecione a malha estática novamente e você pode ver que agora temos nosso material selecionado. O elemento zero é o corpo do avião. Essa é a cor principal e o detalhe. elemento um é um slot de material separado criado exclusivamente para a hélice de madeira Isso nos permite fazer coisas como animação baseada em vértices através do sombreador para fazer a hélice pareça estar se Um pouco complexo para este projeto, mas os recursos existem se você quiser estendê-lo posteriormente. Se derrubarmos o elemento zero, queremos procurar o material inimigo. E, claro, se você seguir as etapas extras recomendadas entre os tópicos, talvez tenha alguns materiais diferentes para escolher. Selecionaremos este, e você verá que meu avião ficou verde, então isso deve se destacar em relação ao modelo e material padrão do avião do jogador. Em seguida, vamos querer adicionar um pouco de movimento ao nosso inimigo. Então, se passarmos para o gráfico de eventos, faremos a mesma coisa de antes, removemos a sobreposição inicial do Acta Não vamos usar isso e podemos nos concentrar no evento ti. Algo que é sempre útil adquirir hábitos é realmente planejar com antecedência os recursos que você implementará. Poderíamos fazer isso, por exemplo, analisando o projeto de exemplos de conteúdo no qual estamos baseando isso e detalhando as principais funcionalidades e recursos que os inimigos terão A primeira é que o movimento não é o mesmo dos jogadores. Não tem aquele impulso falso ou esse tipo de pseudofísica acontecendo É mais rápido, eu apenas me movo para a esquerda, direita e para baixo na tela. Então, temos movimento diagonal. Isso nos permite planejar um pouco com antecedência , porque também podemos ver as coisas quando o inimigo bate na parede e ela muda de direção. Portanto, sabemos que precisamos fazer alguns movimentos para os lados e para frente e, quando eles atingem as paredes, precisamos fazer algo para compensar a mudança direcional Estruturar nossos projetos dessa forma nos permite dividir logicamente um problema maior em subproblemas que serão mais fáceis de resolver, e podemos dar um passo de cada vez Então, para começar, a primeira coisa que vamos querer fazer é realmente adicionar o deslocamento do ator, o mesmo tipo de deslocamento posicional que tínhamos Então, a partir do pino EventiceExecution aqui, vamos pesquisar a localização Então, novamente, muito parecido com o que fizemos no player. Também queremos usar a mesma abordagem para descobrir onde o ator está no momento e seguida, adicionar um deslocamento a isso Então, usaremos a localização do ator get e faremos coisas muito semelhantes antes. partir daqui , procuraremos adicionar ou simplesmente pressionar o botão de adição. Vamos descobrir o cálculo primeiro antes de conectar qualquer coisa e, depois de terminar e pronto, podemos conectá-lo e testá-lo para ter certeza de que estamos começando com o pé direito Já sabemos que não queremos números mágicos, então podemos muito bem criar algumas variáveis que eu já posso ver que precisaremos. O primeiro será um valor de ponto flutuante para a velocidade de movimento. Só uma dica rápida aqui. Se você criar uma nova variável aqui, por padrão, ela será um booleano Na verdade, podemos manter este . A forma como estamos dirigindo o movimento será verificar se estamos nos movendo para a esquerda ou para direita. Então, enquanto temos isso? Vamos chamar isso de movimento B para a esquerda. Então, isso era apenas para dizer que sempre que você criar uma nova variável, você receberá um booleano Um atalho que eu gosto de usar, sabendo que preciso de um valor de ponto flutuante para a velocidade de movimento, semelhante ao que usamos antes Podemos puxar esse alfinete verde aqui. O verde indica que os segundos Delta são um valor flutuante. Coloque isso no gráfico e clique em Promover para variável. Vamos dar a essa o nome de velocidade de movimento. E essa é apenas uma maneira rápida de obter uma variável do tipo que você está procurando sem precisar usar o menu suspenso e encontrá-la no gráfico Você pode fazer isso de qualquer maneira, mas é bom se precisarmos de um vetor, por exemplo, podemos encontrar um vetor aleatório, colocá-lo no gráfico, promover a variável e dar a ela um nome assim. A única coisa é que precisamos fazer uma limpeza, então excluiremos os nós Ainda não precisaremos deles. Mas eu só queria apresentar maneiras diferentes de trabalhar com o editor gráfico do Unreal Engine O vetor foi apenas um exemplo, então selecione isso e exclua essa variável também. E estamos prontos para continuar. Quando se trata do movimento, já abordamos a independência da taxa de quadros e por que precisamos dela, para que possamos incorporá-la desde o início. Se clicarmos com o botão direito do mouse e pesquisarmos os segundos do Get Wild Delta , podemos usar isso em nossos próximos cálculos. Para o movimento, vamos querer medir nossa velocidade de movimento. E se clicarmos em Compilar e apenas certificarmos de que isso tem uma variável, definiremos isso para algo como 250 Isso seria perfeitamente adequado para testes. E, como mencionei, precisaremos de dois cálculos separados. Vamos querer um para o movimento lateral e outro para o movimento para frente na tela Para o movimento para frente, podemos medir nossa velocidade de movimento. Podemos multiplicar isso por um valor para inverter isso, então vamos considerar isso como negativo porque a tela abaixo, como mencionei, é um valor negativo, e se você quisesse subir na tela, seria um valor positivo Portanto, o movimento para frente do inimigo é, na verdade, relativamente simples. E, é claro, queremos multiplicar esse resultado por segundos Delta para manter a taxa de quadros independente Então, esse seria essencialmente nosso movimento para frente pronto para ser testado. Para o movimento lateral, vamos querer fazer algo com nosso valor booleano Então, vou pegar a velocidade de movimento e duplicá-la Vamos querer fazer algo muito semelhante aqui onde vamos pegar um nó de multiplicação, mas obviamente não vamos querer multiplicar apenas um ou menos um Precisamos transformar isso em algum tipo de operação condicional A forma como vamos usar o booleano é um stick verdadeiro ou falso Nós diríamos que estamos nos movendo para a esquerda ou não estamos nos movendo para a esquerda, então estamos nos movendo para a direita. Agora, se você tentou isso, nr converterá um booleano em uma multiplicação de ponto flutuante Infelizmente, os booleanos só são lidos como zero ou um, zero quando é falso, um quando é verdadeiro Obviamente, isso significaria que isso não funcionaria para nosso caso de uso atual, porque se estivéssemos multiplicando por zero em vez de nos movermos para a esquerda, isso apenas pegaria a velocidade do movimento multiplicaria por zero, o que cancelaria qualquer O que poderíamos fazer, porém, se pressionarmos Alt e clicarmos com o botão esquerdo aqui, podemos usar algo chamado de nó de seleção. Então, a partir daqui, vamos pesquisar por Selecionar. E queremos essa opção na parte inferior. Isso nos dá algumas opções. Se estivermos trabalhando com coisas como números inteiros como curinga aqui, você pode ver que adicionamos qualquer número de números Seja qual for o número inteiro que você colocar aqui, ou seja, qualquer número inteiro, se você colocar um número inteiro de um, por exemplo, poderíamos dar a isso um valor negativo aqui Em vez disso, o que queremos fazer é usar nosso booleano Vamos inserir isso no índice aqui, o curinga, e o Unreal mudará isso para ser um booleano para E podemos ver que isso agora está definido como verdadeiro ou falso. Então, a maneira de lermos isso para tornar isso mais intuitivo e fácil de entender é que, se quisermos ir para a esquerda, estamos nos movendo para a esquerda? Se isso for verdade, então o valor precisa ser menos um porque queremos mudar para um valor negativo. Se mover para a esquerda é igual a falso, então não estamos nos movendo para a esquerda, então queremos que o valor seja um. Então, essencialmente, isso está indo para a direita. Isso está se movendo para a esquerda, e isso vai ser positivo e isso vai ser negativo. Portanto, uma boa maneira simples de usarmos um valor booleano para essencialmente ativar o movimento para a esquerda ou E então, quando você fizer a mesma coisa novamente, usaremos nossos segundos Delta. Vamos fazer nosso cálculo aqui, multiplicá-lo por segundos Delta para garantir que ambas as direções sejam independentes da taxa de quadros, e poderíamos essencialmente começar a conectar Então, só para manter as coisas organizadas, vou puxar o pino vetorial aqui e pesquisar por make vector Então, já vimos isso antes. Isso nos dará apenas os três valores de ponto flutuante expostos. A frente em desenrolar está no eixo X. Sideways está no eixo y, e é mais ou menos isso. Nós podemos conectar isso. Poderíamos testar isso e teríamos um inimigo em movimento. Então, se clicarmos em compilar, salvar, voltaremos ao nível principal, podemos simplesmente derrubar nosso inimigo Realmente não importa onde isso vai ficar, desde que esteja um pouco acima da tela do player. Vou fazer uma rotação de 180 graus no eixo z, para que fique voltado para o jogador. E então podemos clicar em play, e devemos ver isso se movendo para baixo na tela. Temos isso se movendo na direção diagonal, que é a parte inicial do problema. Então essa é uma das etapas resolvidas. Acho que notei um pequeno problema aqui. Parece que vamos atravessar a parede invisível. Então, sim, definitivamente fizemos o inimigo ultrapassar a parede invisível. Acho que está dentro dos limites. Como mencionei, algo que é muito fácil de esquecer, e acabei de fazer isso de novo, é que queremos garantir que pressionamos o botão de varredura, então certifique-se de que estamos varrendo e que não devemos ter a mesma funcionalidade do player, mas vamos simplesmente bater na parede invisível Perfeito. Então essa é a próxima parte do problema. Essa é a próxima etapa que precisamos resolver. Quando o inimigo atinge a parede, queremos pegar essa informação e alternar a direção do movimento E nós já meio que temos isso configurado. Então, ainda temos nossa jogada. Vamos mudar isso para verdadeiro e fazer com que eles se movam para a esquerda em relação à direção do inimigo. Logo antes de passarmos por isso, eu queria examinar algumas informações sobre o tipo geral de organização do código, coisas que poderíamos melhorar aqui, mesmo antes de fazer uma grande refatoração coisas que poderíamos melhorar aqui, mesmo antes de fazer uma grande Eu coloquei isso propositalmente para torná-lo mais legível e compreensível Mas, na verdade, esse é um código muito ruim antes mesmo de entrarmos no que precisamos refatorar mais tarde Agora, a primeira coisa é que eu só quero fazer com que as pessoas comentem, algo que eu ainda não mencionei Se pegarmos um nó, por exemplo, e pressionarmos C, podemos fazer um comentário. Uma espécie de autodocumentação destinada a nos lembrar o que algo era, por que o cálculo está sendo feito, como foi. E também torna as coisas mais legíveis à distância. Você não precisa comentar tudo. Você pode ter visto certos desenvolvedores compartilharem parte de sua base de código, e pode ter havido comentários espalhados por toda parte Você pode ter visto coisas assim em que eles têm uma variável ou algo muito simples chamado velocidade de movimento, e eles fizeram um comentário dizendo apenas velocidade de movimento. Isso é completamente arbitrário. Não faz nada. Não é útil. E contanto que você esteja nomeando suas variáveis corretamente ou com alguma boa intenção, já sabemos que isso é velocidade de movimento porque esse é o nome da Portanto, não precisamos comentar assim. No entanto, se pegarmos isso e expandirmos para cobrir todos esses nós, o que poderíamos fazer é mudar isso para dizer algo como mover a direção, seguir em frente. E poderíamos até tornar isso mais útil porque, se pressionarmos F dois para voltar a renomear isso, também poderíamos explicar por que estamos usando menos um como multiplicação porque isso não tem um valor Não tem a real utilidade de ter uma variável. Portanto, é meio que válido ter um número mágico aqui, mas, à primeira vista, podemos esquecer por que menos um está sendo aplicado, para que possamos deixar um comentário apenas descrevendo o que está acontecendo Então, podemos dizer aqui que estamos multiplicando isso por menos um para mover os inimigos especificamente para baixo na tela Então faça uma coisa muito parecida. Poderíamos pegar esses nós, pressionar C e fazer um comentário semelhante a este. Este realmente não requer nenhuma explicação. Eu acho que isso está bem claro. Se estivermos nos movendo para a esquerda, pegue o valor relacionado à direção em que queremos nos mover. A principal coisa que obtemos ao fazer isso é que, se começarmos a reduzir o zoom do gráfico, agora podemos ver essa seção sem realmente examinar o código Esta seção é para avançar. Isso é para movimentos laterais. Se você já precisou se aprimorar rapidamente e encontrar um trecho específico de código para corrigir algo ou verificar novamente, sabemos exatamente onde estão, apenas o uso de comentários. Eles podem ser úteis. Você não precisa usá-los em todos os lugares, mas definitivamente em lugares onde você acha que pode esquecer o que está fazendo se voltar em um ou dois meses. Agora, o principal problema que queremos corrigir agora, porém, vou excluí-los é que atualmente estamos fazendo várias duplicações Temos os segundos do G World Delta multiplicados duas vezes aqui individualmente. Então, uma coisa que poderíamos fazer, e isso pode não ter sido completamente óbvio para começar, mas em vez de multiplicar os valores individuais de ponto flutuante aqui, podemos multiplicar Então, se pegarmos os resultados desse vetor make que criamos, extraia daqui e pesquise por multiplicar Podemos pegar um dos nossos segundos Get world to Delta, pressionar Control X para cortar isso e controlar B para colar e , em seguida, conectá-lo aqui. E RL converte isso em um vetor multiplicado por um flutuador. Podemos inserir esse cálculo aqui. E então podemos nos livrar desse nó aqui, então não precisamos mais desse múltiplo e conectá-lo. E podemos nos livrar desses dois nós. Não precisamos nem um pouco disso e depois conectamos isso de volta ao Y. Então agora temos algo um pouco mais organizado Não temos tantas multiplicações acontecendo. Estamos pegando o vetor inteiro agora, que fará a multiplicação de X e Y ao mesmo tempo em relação aos nossos segundos Delta, garantindo que tudo seja independente da estrutura de todo o cálculo Então, essa foi apenas uma rápida organização do código. Então, se clicarmos em compilar e salvar, veremos que obtemos exatamente a mesma resposta para que nada mude Ele parece e se move da mesma forma que antes. A última coisa antes de deixar este tópico para uma noite antes de fazer o fator Ru é que todo inimigo começará a se mover na mesma direção e na mesma velocidade, que será um pouco chato Se adicionarmos alguns inimigos, podemos simplesmente segurar a tecla Alt e arrastar um widget aqui para duplicar imediatamente Então, estou apenas segurando a tecla lt, pegando a direção do widget e arrastando em uma direção que duplicará o que Se apertarmos play, vai parecer algum tipo de nado sincronizado Todos estão indo exatamente na mesma direção, na mesma velocidade. Vai ser um pouco chato. Então, se voltarmos ao início do jogo, mostrarei como randomizar primeiro um booleano para , pelo menos, mudar a direção em que os inimigos individuais podem estar se movendo. Na verdade, isso é muito simples. Vamos segurar a tecla Alt e arrastar o movimento da lança para a esquerda ao lado do início do evento. Ou você pode simplesmente colocá-lo no pino de execução aqui. E então, a partir da variável, queremos arrastar do pino aqui. Vou procurar algo chamado bola aleatória. Então, obteremos um booleano aleatório e definiremos isso no BignPlay Tão super simples. 50% de chance de nos movermos para a esquerda ou para a direita. Então, se pressionarmos play, todos escolheram seguir a mesma direção e fizeram isso de novo. Podemos ver que há alguma randomização, então isso é bom. Eles nem sempre vão seguir exatamente na mesma direção. Então, um pequeno exercício de aprendizado para você. A abordagem para fazer uma flutuação aleatória é um pouco diferente, mas demore alguns minutos, pause o vídeo e veja se você consegue implementar algo semelhante com a velocidade do movimento Portanto, aumente a velocidade de movimento e veja se você consegue encontrar alguma funcionalidade integrada que o UNR possa ter para nos permitir inserir um valor aleatório no ponto flutuante Você pode randomizar isso entre algo como 250, que atualmente é nosso padrão, e talvez 500, para que cada inimigo se mova a uma velocidade ligeiramente diferente Pause o vídeo, experimente e comece a testar o quão confortável você está se sentindo com o sistema de diagramas Ok, então vou explicar como eu teria feito isso. Se conectarmos isso e espero que você tenha experimentado, novamente, eles serão muito valiosos para realmente aprender a usar os planos, em vez de apenas seguir meus passos Mas para que tenhamos o mesmo código, no mínimo, ou algo a partir do qual derivar. O que eu faria é pegar minha variável de voo aqui. Vamos comprar um apartamento aleatório. Essa é a única coisa que pode ter te confundido, e você pode ter querido experimentar algumas opções diferentes. Mas, em vez de usar apenas flutuação aleatória, que forneceria qualquer número, isso poderia ser muito rápido ou muito, muito lento. Portanto, não é muito utilizável. Você também poderia ter tentado coisas como flutuar aleatoriamente do stream Mas o que eu usaria seria essa flutuação aleatória no alcance Então, se selecionarmos este, ele nos dará apenas dois pontos para escolher do nosso mínimo, que eu diria que seria 250, e dobraremos isso para 500 como o máximo. Portanto, alguns aviões podem obter esse mínimo de 250, outros podem obter 500 ou um valor intermediário. E lá vamos nós. Podemos ver que todos eles começam em velocidades completamente diferentes, o que, novamente, tornará as coisas um pouco mais interessantes quando começarmos a adicioná-los e eles estiverem funcionando corretamente no nível, ricocheteando nas paredes e coisas assim Com isso, porém, os inimigos estão se movendo e colidindo com as paredes Eles ainda não saltam e também não interagiriam com o jogador Então, antes do grande fator Ruf, veremos a seguir a detecção de colisões, fazendo com que as coisas realmente aconteçam quando objetos se tocam 12. 11 — EnemyCollision: Tenha inimigos que se movem, mas eles não reagem a nada. Idealmente, quando um inimigo atinge algo, precisamos verificar o que é. É uma parede e, em caso afirmativo , alterne a direção. Se for o jogador, podemos ver novamente no projeto de exemplo que ele aplicou dano a si mesmo e foi destruído. Então, o que faremos é destruir automaticamente o inimigo se ele tocar no jogador. Os projéteis se comportarão sozinhos, então pensaremos nisso um pouco mais tarde Isso não será um problema a ser considerado aqui. Uma coisa a mencionar é que o sistema de colisão irreal é flexível e poderoso, o que, infelizmente, significa que é um tanto complexo Pelo menos quando você começa a trabalhar com ele depois de experimentar algumas iterações diferentes de diferentes tipos de coisas que deseja fazer com ele, acho que ele clica muito rapidamente e é um sistema bastante confortável de se trabalhar Então, vamos voltar para o inimigo panorâmico. Podemos usar isso para testes. Se pegarmos a malha estática e abrirmos a seção de colisão no lado direito, basta rolar até aqui e encontrar nossa categoria de colisão Se deixarmos isso cair, podemos ver a colisão predefinida aqui. Vamos deixar esse aqui. Podemos vê-lo configurado como bloqueado ou dinâmico. Portanto, esta é a nossa configuração de colisão atual. O tipo de objeto também é definido como dinâmico mundial aqui, então esse é o canal de colisão com o qual esse objeto se identifica É por isso que, quando pressionamos play, o inimigo para nas paredes. Essa é uma colisão física ou física em que os dois estão se bloqueando e tentando não habitar o mesmo espaço físico Agora, se derrubarmos essa e mudarmos para sobreposição ou dinâmica, ou seja, o equivalente, mas para sobreposições, clicaremos em compilar e jogaremos mudarmos para sobreposição ou dinâmica, ou seja, o equivalente, mas para sobreposições, clicaremos em compilar e O que veremos é que agora eles voltam pelas paredes. Agora, sob o capô, algo está sendo disparado. Há uma mensagem sendo enviada dizendo que esses três inimigos acabaram de se sobrepor à parede Mas como não é uma interação física, é apenas uma notificação e essencialmente, uma observação de que eles estavam passando pelo mesmo espaço. Você pode pensar em bloqueio versus sobreposição como um jogo de corrida Queremos que as paredes e os arredores bloqueiem os veículos. Se colidir com eles, você é parado. Queremos que os postos de controle se sobreponham. Obviamente, queremos saber se um veículo passou por um posto de controle e a que horas isso aconteceu, mas não gostaríamos que esses postos de controle começassem a impedir fisicamente o prosseguimento dos carros Isso seria um pouco chato. Então, se voltarmos para o peão inimigo, isso foi só para mostrar como eles funcionam de forma diferente Também temos a terceira opção. Temos a opção de ignorar. Agora, isso provavelmente é bastante óbvio. Isso configurará isso para ignorar todos os tipos de colisão. Poderia fazer isso, por exemplo, acessando a opção sem colisão e, embora pareça que está configurado para bloquear, isso está na verdade no código, lendo a opção Ignorar Agora, não haverá nenhuma mensagem disparada. Nada sabe realmente que o avião está passando por ela. E isso é bom para objetos que não precisam ser adicionados à pilha de chamadas e à pilha de verificação de colisão . Muito bom para o desempenho. Mas, geralmente, trabalharemos com sobreposição ou bloqueio, dependendo do que precisamos que eles façam Nesse caso, podemos voltar ao padrão, que é a dinâmica de blocos. Eu fiz isso apenas pressionando aqui. Você pode ver a pequena seta. Se você quiser redefinir as propriedades para o padrão, basta pressionar isso, e isso voltará ao que era antes de ajustarmos as coisas Com a malha estática ainda selecionada, queremos rolar ainda mais para baixo no painel de detalhes até a parte inferior. E temos essas opções aqui, os eventos. Agora, não vamos passar por todos eles. Novamente, as coisas em que mais nos interessaremos serão o impacto de um componente. Isso acontece quando duas coisas se bloqueiam fisicamente e um componente começa a se sobrepor e, às vezes, na extremidade do componente Eles são chamados quando dois objetos sobrepostos entram ou saem Portanto, podemos obter a sobreposição final porque, como vimos, colisões sobrepostas permitem que os objetos habitem o mesmo espaço habitem Queremos vincular nossa verificação de parede à função de início de batida do componente on aqui Isso cria um novo evento de cliente para nós, então a função, que é chamada toda vez uma colisão é detectada em nossa malha estática Então, se você se lembra, toda vez que criamos nossa classe e tínhamos aquela função padrão, realmente não precisávamos da verificação da função actor hit, que sempre excluímos. Isso foi essencialmente algo semelhante, mas, como mencionei, para toda a turma. Já que agora podemos nos concentrar e verificar especificamente se apenas a malha estática foi atingida, podemos fazer algo depois Esses nós, na verdade, fornecem muitas informações. Por exemplo, se clicarmos com o botão direito do mouse no pino da estrutura de ocorrência aqui e selecionarmos a opção de dividir a estrutura, podemos ver todas as informações que podemos recuperar sempre que algo nos atinge ou atingimos algo. Podemos descobrir a hora. Podemos descobrir se o bloqueio foi bem-sucedido. Podemos ver o local real do impacto e o ponto de impacto. Podemos obter coisas como a rotação a partir disso, o tipo de material físico e assim por diante. Não precisamos de tudo isso no momento, mas é útil, novamente, quando você começa a ficar mais avançado e confortável com o irreal Se quiser fazer coisas sofisticadas com coisas como penetração de balas ou o tipo de resultado que acontece quando duas coisas colidem, você pode definitivamente mergulhar aqui e entanto, clique com o botão direito em qualquer um desses pinos recombine o pino da estrutura apenas para arrumar esse As principais coisas com as quais costumamos trabalhar quando trabalhamos com colisões são saber um pouco de informação sobre o outro ator, porque, no momento, não sabemos o que nos atingiu Só sabemos que fomos atingidos quando isso foi chamado. Pode ser a parede, pode ser um jogador, pode ser outro inimigo. Então, isso vai se tornar útil para ler mais tarde, então podemos também promover isso para uma variável agora, e chamaremos isso de ator de sucesso. E é por isso que eu só queria dedicar um momento rápido para percorrer diferentes maneiras pelas quais você poderia até mesmo considerar abordar a solução desse problema, descobrindo o que nos atingiu Em muitos projetos estudantis que eu reviso e com os quais trabalho, vejo muitos lançamentos porque muitos tutoriais muito básicos que você pode encontrar on-line tendem a mostrar como transmitir para outros objetos, porque é uma maneira rápida e simples de obter Em nosso projeto, o que estamos fazendo é relativamente pequeno e simples, então, na verdade, não pareceria muito ruim. Mas se você fosse seguir esse caminho, talvez tivesse algo que acabasse parecido com isso. Eu só vou fazer uma rápida pausa. Corte rápido Como eu disse, isso é essencialmente o que você acabaria com. A maneira como um elenco funciona, e eu quero apresentar a vocês o elenco de qualquer maneira, a forma como o elenco funciona é que, quando estamos trabalhando com nosso outro ator, se destacarmos o alfinete aqui, podemos realmente ver o que está sendo devolvido. Então, vou clicar em compilar. E eu passo mouse sobre as informações do outro ator Isso está nos mostrando que isso está fornecendo uma referência para o ator. A razão é que, se nos lembrarmos hierarquia de herança da Unrelengin, tudo com o qual podemos interagir no mundo que tem uma presença física, essa transformação precisa ser de um essa transformação precisa ser Então, ao fornecer um alfinete aqui, que é o objeto mais básico que podemos encontrar no mundo, um ator, podemos garantir que possamos comparar tudo e, em seguida, nos concentrar especificamente no tipo de ator, funcionalidades e recursos extras que ele contém Agora, a maneira de fazer isso, ou eu já vi isso muitas vezes em muitos tutoriais, é que eles mostram que você pega algo como o ator que você atropelou e nós contrariamos isso E o que é isso é essencialmente uma pergunta. Está dizendo que esse ator genérico, eu posso ver que o ator genérico existe. É especificamente o tipo de base de peões, que para nós é o jogador Se for, então isso é verdade, sim, é uma base de panela, então faça isso aqui. Então, chamaríamos a função específica da classe do jogador, que, como mencionei, é aplicar dano ao jogador e depois se distrair Se não for, então, se fizermos essa verificação e ele voltar como não sendo o jogador que atingimos, então acertamos outra coisa. Então, iria para o elenco f. E então você veria pessoas fazendo um segundo elenco. Então, ficamos como uma cascata de fundição, que é E se entrarmos em projetos muito maiores, você pode ver que só temos três coisas a considerar. Mas se tivermos coisas diferentes, como picapes obstáculos e muitas outras coisas que talvez precisemos considerar, teremos uma cachoeira em cascata muito maior Mas a próxima coisa que você pode fazer novamente é voltar aqui e dizer que o objeto genérico, o ator genérico, é especificamente um inimigo? Se for, faremos as coisas do inimigo, o que, no momento, ainda não decidi como vamos lidar com os inimigos. Acho que eles vão se superar gradualmente, mas precisamos fazer essa função. Caso contrário, verificaremos novamente. Então, podemos usar algo como o volume de bloqueio, se as coisas estiverem bloqueando o volume, se isso for verdade, então sim, batemos em uma parede e mudaremos de direção. Portanto, essa é uma maneira de você ver isso feito. Pode ter sido assim que você pensa em fazer isso se estiver ciente do que o elenco faz. E eu só queria fazer um resumo geral de por que não faremos isso e por que devemos tentar evitar isso sempre que possível É outra coisa que se repete com muita facilidade como a declaração geral de nunca usar carrapato Você ouvirá as pessoas dizerem que nunca use o casting. Novamente, isso é realmente muito simplificado. Há vários motivos pelos quais gostaríamos de usar a fundição onde ela possa ser totalmente segura e muito barata de fazer. Está um pouco fora do contexto desse tópico. Então, no momento, vamos apenas dizer, eu vou deletá-los. Não faremos isso simplesmente porque não queremos esse efeito de cascata Onde estamos verificando por objeto. Então, para simplificar as coisas, vou dividir isso em duas coisas diferentes para este projeto que queremos muito verificar. Queremos verificar a parede e queremos verificar o jogador humano. Acho que, apenas para criar o jogo e para fazer com que ele se sinta melhor, acho que vou deixar os inimigos se enfrentarem para que o jogador só precise considerar o caminho que está tomando entre o impacto e as paredes. Então, isso realmente os torna muito, muito simples. Para começar, podemos fazer uma verificação muito simples. Podemos clicar com o botão direito do mouse no gráfico do evento e pesquisar por Obter peão do jogador Portanto, essa é uma função embutida. O motor Unreal está sempre rastreando o que é classificado como peão do jogador, que é o que o jogador humano Então, quando pressionamos play, essa seria a nave azul. Então, o que podemos fazer aqui? Isso evita a fundição, o que é uma coisa útil. Não precisamos obter todas as informações dessa outra classe. Isso também significa que, se tivéssemos mais recursos, como deixar o jogador escolher entre cinco classes de plantas diferentes com navios completamente exclusivos, novamente, não precisaríamos comparar cada navio exclusivo Só precisamos saber se o que atingimos é uma nave de jogador, e saberíamos disso a partir desta verificação aqui. Então, podemos retirar desta caixa e procurar por dois iguais, ou seja, apenas dois sinais de igualdade. E vou desengatar isso para torná-lo um pouco mais legível Conecte isso de volta. Podemos apenas dizer: É o ator de sucesso? Então, a coisa com a qual acabamos de colidir também é especificamente a coisa que o jogador está controlando Podemos então extrair nosso booleano aqui. Podemos procurar uma filial. Podemos inserir isso em nosso pino de execução e simplificar o código que precisamos verificar. Então, se a coisa que atingimos for o jogador, se isso for verdade, então vamos causar nosso dano. Então, talvez queiramos apenas uma sequência de caracteres impressos aqui para nos lembrar de voltar. Então, vou usar uma string de impressão porque ainda não temos funções de danos e coisas assim, mas vou torná-la grande e negrito para que, toda vez que isso acontecer, isso nos lembre de voltar e alterar o código. Então, é aqui que aplicamos danos ao jogador. E então, a destruição de nós mesmos é, na verdade, muito simples Só precisamos chamar a função destroy actor. Podemos colocar isso aqui. E isso na verdade, faz parte do conjunto de recursos, já feito. Então, agora, se eu deixasse os aviões inimigos caírem, eles estariam prontos para causar danos, embora ainda não tenhamos saúde e tudo mais, e então eles se destruirão. Agora, partindo do galho falso, novamente, na verdade, muito simples, agora nos diz que, se vamos permitir que os inimigos se superem , não estamos preocupados com isso, o que significa que , se batermos em outra coisa terá que ser uma parede. Essa é a única outra coisa com a qual podemos colidir neste projeto Então, podemos fazer isso a partir da ramificação falsa aqui. E o que queremos fazer é definir o movimento para a esquerda. Então, vou conectar isso ao pino de execução. Mova isso para cá. E, novamente, apenas para considerar a maneira como você pode fazer isso. Quando você está se acostumando com o fluxo de código, você pode ficar tentado a usar um Banchon então estou apenas pegando Isso os conectará automaticamente e você poderá fazer algo assim. Portanto, verifique o valor do movimento para a esquerda. No momento, estamos nos movendo para a esquerda? Se sim. Então, se a esquerda for verdadeira, então queremos que isso seja falso, e se a esquerda não for verdadeira, então queremos que isso seja invertido e transformado em verdadeiro Então, essa é definitivamente uma maneira de fazer isso. Mas, novamente, eu só quero mostrar uma maneira limpa de fazer isso. Então, se colocarmos isso de volta aqui, podemos movê-los para fora do caminho. Na verdade, vou excluí-los do nosso booleano aqui, vou puxar e pesquisar algo chamado bola de nó ou não A maneira como isso funciona é basicamente se isso for verdade, isso retornará falso. Se isso for falso, isso retornará verdadeiro. Então, podemos pegar esse valor e, essencialmente, ele sempre inverterá qualquer que seja o booleano atual Então, se estivermos nos movendo para a esquerda, isso nos fará mover para a direita, e se estivermos nos movendo para a direita, isso nos fará mover para a esquerda. Então, uma versão simples e bonita do que poderia ter sido uma estrutura de ramificação extra da qual não precisávamos. E é mais ou menos isso. Ou seja, nossa saúde sendo contabilizada quando abordamos esse assunto um pouco mais tarde, a destruição ao entrar em contato com o jogador e, em seguida, a mudança de direção quando batemos em uma parede Então, se voltarmos e apertarmos play, podemos ver que eles estão se recuperando, que eu acho que seria uma implementação perfeitamente boa, dependendo de você E então, se eles atingirem o player, podemos ver no canto superior esquerdo a sequência impressa estava sendo chamada e eles estavam sendo removidos. Então, novamente, tudo se resumirá ao design. Se você quiser que eles se recuperem, podemos deixar essa funcionalidade ativada Se você quiser que eles se superem gradualmente, mostrarei isso quando entrarmos mais tópicos de colisão, um pouco mais tarde Mas é isso. Agora temos uma implementação funcional. E, como mencionei, a razão pela qual isso está funcionando é toda vez que uma colisão é detectada nesta classe agora, será automaticamente disparada Ele está rastreando todas essas informações sobre o que foi atingido e o que aconteceu, e então extrapolamos a partir dessas informações o que é relevante apenas para o nosso projeto Vamos fazer algo muito inteligente com os projéteis, então também não precisaremos considerar projéteis quando eles atingirem o inimigo Isso será tratado no código do projétil. Então, tudo o que o inimigo precisa saber é o jogador e as paredes, que na verdade é outro princípio de programação, que é muito importante, especialmente em linguagens como C plus e blueprint, porque basicamente ainda se baseia nesse fluxo de trabalho no engem real O conceito geral é que tentamos tornar uma turma o mais específica e pequena possível. Então, foi feito para fazer uma coisa e uma coisa bem. Um exemplo de código incorreto em uma classe inimiga seria rastrear quais captadores o jogador pode ter segurado, verificar coisas como qual projétil acabou de atingi-lo, quanto dano esse projétil deve causar e coisas assim, porque essa é a lógica Todas as coisas relacionadas aos danos causados por um projétil devem ser armazenadas no projétil e essas informações devem ser repassadas O inimigo só deve considerar e ser responsável por coisas relacionadas ao inimigo. E neste caso, isso é se mover e bater em paredes, uma entidade muito simples Então, apenas outra rápida olhada no que seria classificado como código limpo é o encapsulamento de garantir que sua classe, em geral, a regra seja, como eu disse, fazer uma coisa e fazer uma coisa bem Com isso configurado e pronto, porém, agora temos uma turma completa pronta para ser reestruturada Então, a seguir, vamos examinar o tópico da herança. Essa será a melhor maneira de lidar com muitos códigos e recursos compartilhados que estamos vendo atualmente no inimigo e no jogador. Estamos duplicando muito trabalho, então será hora de corrigir isso 13. 12 — Base Class de herança herança: É hora de consertar a bagunça que fizemos. Duplicamos a configuração da malha. Estamos lidando com o movimento de forma diferente, mas seguindo a mesma lógica estrutural duas vezes. Isso parece pequeno no momento. Mas quando adicionarmos saúde, destruição e efeitos, tudo isso começará a se agravar. Cada recurso compartilhado significa o dobro do trabalho para nós, mas também significa potencialmente o dobro dos bugs. Também na classe de peões, atualmente estamos usando toda a malha como um colisor, que realmente não é ideal para esse tipo de jogo A maioria dos jogos de ação ICD como esse, na verdade, usa um truque para fazer o jogador se sentir um pouco mais inteligente do que realmente é Quando você pensa que se esquivou de algo com habilidade, mas na verdade acabou de sobreviver, é bom, mas isso porque seu colisor provavelmente é um pouco menor do que um pouco menor do Vamos querer implementar algo assim para que comece a parecer realmente interessante interagir com nosso jogo . Apenas uma pequena forma de manipulação psicológica, mas faz com que o jogo pareça justo, mesmo quando a matemática diria o contrário A maneira de resolvermos isso é usando um colisor de esferas como a nova rota em vez da malha A malha funcionará apenas como decoração totalmente livre de colisões Ambas as classes precisarão disso, então podemos muito bem construir isso apenas uma vez e compartilhar componentes e recursos como esses em todas as classes. A maneira de fazer isso é com algo chamado herança Já mencionei anteriormente que o UnrelEngine é um software altamente baseado em herança, então seguiremos o mesmo tipo de então seguiremos o mesmo Basicamente, significa que podemos codificar algo uma vez no que é chamado de classe principal ou base. Podemos então criar classes secundárias disso, que herdarão todos os componentes, os recursos e os sistemas que inserimos Por exemplo, vimos os atores fornecerem uma transformação, uma escala de rotação de localização no mundo, e então os peões pegam essas informações e constroem sobre elas , recebendo a mecânica a ser possuída e muitas outras e constroem sobre elas , recebendo a mecânica a ser possuída e muitas outras coisas. Chega de falar. Vamos ver isso em ação. Então, vamos começar a criar nossa nova classe base que nos ajudará a ver o sistema na prática. Se voltarmos às plantas e à pasta principal, criaremos algo completamente novo Clique com o botão direito do mouse na janela e voltaremos para a classe Blueprint e criaremos um novo peão Vou mudar isso de ser chamado de sublinhado de peão para base plana de sublinhado da BP em vez Todos eles serão aviões, então podemos deixar claro nossa convenção de nomenclatura aqui Dentro de nossa nova classe, abordaremos os componentes e adicionaremos o componente esférico que mencionei. Não estamos procurando esse aqui. Esta é uma esfera visual sólida em três D. Só queremos uma ligação em colisão. Se pesquisarmos a palavra colisão, podemos ver aqui que temos algumas opções diferentes Queremos nosso colisor de esferas, que aplicará isso aqui, e podemos fazer a mesma coisa que fizemos antes Podemos arrastar isso para a raiz padrão da cena para torná-lo nosso novo componente raiz. Em seguida, podemos voltar ao botão Adicionar. Ainda queremos nossa malha estática. Isso simplesmente não vai mais lidar com colisões . Faremos a mesma coisa novamente. Vamos até nossa malha estática aqui e selecionaremos nosso herói do plano de sublinhado SM Com a malha estática ainda selecionada, podemos ir até a seção de colisão aqui e, na verdade, podemos simplesmente usar essa lista suspensa e pedir que ela não faça nenhuma detecção de colisão Também podemos desativar a sobreposição de eventos gerados. Isso apenas garante que nada esteja sendo verificado relação à malha estática em nenhum ponto. Perfeito porque queremos que isso seja visual. Isso significa que ele não precisa ser adicionado à pilha de colisões Está meio que sentado lá sendo renderizado. Se também selecionarmos nosso colisor de esferas , podemos fazer algumas alterações aqui Se colocarmos isso no lado direito na seção de colisão novamente, queremos mudar isso de sobreposição ou dinâmico, e podemos realmente tornar isso mais distinto do que isso, e diremos que isso seja classificado como uma Então, veremos que isso muda a predefinição de colisão para O tipo de objeto agora é rastreado como um peão e é feito algumas coisas aqui Não vou deixar por isso mesmo se quisermos flexibilidade total. Vamos considerar isso como a predefinição padrão, mas podemos personalizá-la soltando-a novamente e selecionando Então, ainda temos esse conjunto como peão. Ainda temos as configurações de colisão ativadas conforme desejamos e temos tudo isso definido por padrão podemos achar que queremos No entanto, podemos achar que queremos voltar e fazer com que isso não se sobreponha a outros peões ou bloqueie outros peões, faça algo diferente com a estática mundial, e agora temos a opção de alterá-la se quisermos. Não faremos isso agora. Faremos isso com base em testes e vendo como o projeto se desenrola Com isso feito, isso está nos colocando em uma posição muito boa, no entanto. Cada classe secundária agora herdará esse conjunto. Então, isso significa que configuramos isso uma vez e nunca mais precisamos pensar nisso novamente. Então, agora podemos começar a analisar nossa funcionalidade compartilhada, bem como na captura de eventos, o tipo de coisas que queremos compartilhar entre as duas classes. Como sempre, vamos pegar o evento para começar a sobrepor e excluir este E para o movimento, há algumas coisas a considerar. Mais uma vez, apenas com base na recriação do projeto de exemplo estamos tentando atingir algum nível de paridade: há um pequeno recurso se você realmente observar o que está acontecendo quando os aviões e o jogador não se movem ou alinham o movimento no início Eles reproduzem uma pequena animação. Eles animam a tela por talvez um ou dois segundos e, em seguida, permitem que o movimento vá para os lados Então, vamos fazer algo muito parecido. Vamos congelar ou pausar qualquer entrada de movimento até que a animação seja lançada. Veremos as animações na seção de aprimoramento, mas precisamos pensar novamente no que precisaremos considerar e podemos programar isso agora Então, vamos começar com isso. Vamos querer fazer uma verificação muito simples e lógica. Então, se retirarmos nosso pino de execução, vamos procurar uma ramificação. E da filial, podemos medir a condição aqui. Vamos promover isso para uma variável imediatamente. Chame isso de B, movimento ativado. Vamos clicar em Compilar e garantir que o padrão seja verdadeiro. Então, se o movimento estiver ativado, que queremos fazer enquanto estamos apenas depurando antes de configurarmos a animação, se o movimento estiver ativado, permitiremos que movimento estiver ativado, permitiremos o inimigo voe de um lado para o outro e desça pela tela, e permitiremos que o jogador voe de um lado para o outro com base na Caso contrário, isso significa que provavelmente estamos na animação e chamaremos a função false aqui e impediremos qualquer movimento aconteça. Então, isso só nos configura. Mais tarde, quando chegarmos a esses recursos, pensando no futuro, não precisamos refatorar completamente o código novamente. próximo passo é que as duas classes precisarão de algum tipo de movimento. Mas, como mencionei, estamos programando o movimento de forma um pouco diferente, então não podemos compartilhar o código de movimento real porque não há o mesmo tipo de movimento sendo usado. Mas o que podemos fazer é compartilhar o fluxo lógico e os conceitos da funcionalidade que precisaremos. Podemos fazer isso dando uma olhada nas funções agora. Então, no lado esquerdo, temos essa categoria de função aqui. Assim como os eventos, podemos criar nossas próprias funções personalizadas e, em seguida, chamaremos a lógica quando essa função for chamada da mesma forma que fizemos com eventos no passado. Então, se pressionarmos mais aqui, e eu vou chamar essa nova função, criamos o movimento da alça. E você pode ver uma das diferenças aqui Na verdade, um dos principais benefícios de usar funções em vez de eventos é que elas fazem praticamente a mesma coisa. Eles respondem ao serem chamados, mas aqui temos nosso próprio gráfico de funções. Então, está meio escondido e, novamente, mantendo as coisas bem arrumadas Agora, não vamos realmente lidar com nenhuma das funções de movimento aqui. A forma como isso será usado é que substituiremos essa função em nossas classes filhas posteriormente, mas precisamos que ela exista para ter algo para chamar O que queremos fazer é voltar ao gráfico de eventos. Queremos usar nossa função de movimentação de alças. E vamos colocar isso no pino verdadeiro. Então, se um movimento estiver ativado, chamaremos a função de movimento da alça. Então, novamente, ele se torna agradável e legível. E quando realmente implementamos isso, podemos ter uma ideia do que exatamente vai acontecer. Então, isso é meio simples por enquanto. Você verá isso se desenrolar e fazer muito mais sentido quando realmente começarmos a implementar as coisas Essa é uma daquelas coisas em que eu poderia tentar passar cinco a 10 minutos descrevendo o que faremos mais tarde, mas acho que fará muito mais sentido simplesmente implementá-la à medida que avançamos. Outra coisa é que ambas as classes simples precisarão do inimigo do jogador e dos chefes ou do que você quiser começar a herdar dessa classe Todas precisarão ser destruídas ou mortas em algum momento Então, enquanto estamos aqui, podemos muito bem adicionar outra função, e vou chamá-la de handle death. Novamente, não vamos colocar nada aqui agora, mas uma coisa que podemos fazer com essa função, coisas genéricas, como tudo, precisarão reproduzir um efeito sonoro ou um efeito de partícula quando eles morrerem Podemos fazer isso nesta classe aqui porque essa é uma função universal. Isso é algo que, independentemente do tipo de avião, todos precisam mostrar algum tipo de feedback quando isso acontece. Portanto, podemos fazer a funcionalidade universal aqui. E então, se houver algo exclusivo no plano individual, podemos substituir novamente a funcionalidade que está acontecendo aqui e , em seguida, fazer algo além disso Então, apenas uma ideia aproximada de como a herança funciona e como podemos usar esse código reutilizável, economizando tempo e esforço à medida que avançamos Agora, a última coisa que eu posso imaginar que ambas as classes de aviões precisarão é a velocidade de movimento. E nós meio que já sabemos disso. Se analisarmos nosso próprio código, uma das poucas coisas que os dois têm é abrirmos os gráficos de eventos, pan base, ou seja, o player tem muito mais funcionalidades Há muito mais variáveis aqui, mas tem velocidade de movimento. E então a panela é um pouco diferente, simplificada. Embora não estejamos fazendo a verificação de movimento para a esquerda na versão para jogadores, ainda estamos usando a velocidade de movimento. Então, coisas assim são o que estamos procurando em nossas classes básicas. Coisas que tivemos que implementar mais de uma vez são algo que poderíamos simplesmente colocar diretamente na classe base Então, aqui, o que eu vou fazer é criar uma nova variável chamada essa velocidade de movimento. E trocamos este por um flutuador, empilhamos e salvamos E sempre que precisarmos usá-los entre as aulas, estarão disponíveis e prontos para uso. Novamente, ainda não precisamos usá-lo, mas isso está apenas estabelecendo as bases para que tenhamos uma transição mais suave e agradável E, na verdade, essa é a nossa classe base desenvolvida tanto quanto precisamos agora Podemos voltar e adicionar coisas mais tarde, mas temos os componentes compartilhados de que precisamos: a colisão unificada, o movimento pronto para ser implementado em cada turma infantil mesmo vale para a morte e, em seguida, para a variável de velocidade pronta para uso. Então, só para dar uma olhada rápida em como podemos usar essa classe base, adicionaremos a funcionalidade completa um pouco mais tarde, mas com uma demonstração muito rápida. Se voltarmos ao nosso sorteio de conteúdo, podemos clicar com o botão direito do mouse na Base simples. E aqui em cima, temos a opção de criar uma classe secundária de Blueprint Se clicarmos neste, isso criará um novo modelo para nós Isso herdará tudo do Base simples. Vou chamar isso de jogador de avião BP underscore. E então, se clicarmos duas vezes para abrir este, podemos ver que agora vem pré-construído com nossa esfera e nossa malha estática. Também temos algumas outras coisas aqui. Se clicarmos na opção de substituição, podemos ver, na verdade, as funções que criamos manualmente, lidar com a morte e lidar com o movimento, especificamente em nossa classe base Se clicarmos neles, isso nos dará uma função para que possamos começar a usar a versão principal da função , como mencionei, fazer nossas próprias coisas além e, como mencionei, fazer nossas próprias coisas além disso. Nossos controles de pressão para se livrar desse por nove. Ainda não queremos fazer nenhuma substituição e não precisamos mudar nada ainda, mas eu também gostaria de mostrar outra maneira adicionar classes com base nas que temos Se você voltar ao sorteio de conteúdo mais uma vez, clique com o botão direito aqui e, desta vez, vamos assistir a uma aula de diagramação, algo que pode não ser muito óbvio Mas muitas pessoas pensam que isso se restringe às classes de mecanismos irreais e às criadas por desenvolvedores não relengin Mas, na verdade, assim que criamos uma classe, podemos realmente encontrá-las aqui. Então, se eu procurar uma base simples, podemos ver aqui que a base simples é filha de um peão e um peão, como eu disse, é filho de um ator E nosso jogador simples está em uma criança de base simples. Então, agora podemos selecionar nossas próprias classes da nossa lista de classes aqui no editor. Então, selecionaremos a base simples novamente. Selecione este. E, claro, vamos chamar esse avião BP Underscore Então, ambos estão prontos para começar quando começarmos a desenvolver as coisas. Só queria mencionar, também, que existem várias maneiras de usar suas classes básicas quando você as tiver prontas e configuradas. Feito isso, a classe base está pronta, no entanto. Como eu disse, temos os componentes compartilhados, a funcionalidade compartilhada e a configuração unificada de colisão Em seguida, vamos refatorar o player primeiro. Pegaremos o grande , examinaremos o código fragmentado que vamos percorrer e depois nos concentraremos no inimigo 14. 13 — RefactoringPlayer: A aula está pronta para começar. Então, agora vamos precisar converter nosso player para fazer uso disso. Isso é conhecido como refatoração, essencialmente reestruturando o código existente sem alterar Nosso objetivo é o mesmo comportamento mas uma melhor organização e redução da sobrecarga ou da reutilização de variáveis, componentes e coisas do tipo, sempre que possível Percebi que, no tópico anterior que acabamos de abordar, dei instruções para criar duas novas classes de aviões. Há uma outra coisa que eu percebi no meio que poderia ser útil conhecer e, na verdade nos pouparia um pouco mais de tempo. Então, o que eu vou recomendar é que, na verdade, excluamos o inimigo simples e o jogador comum. Assim, podemos pegar esses Shift Select e pressionar Delete. , não fizemos nada nisso, então não estamos perdendo nada e, pelo menos você sabe que essas opções estão disponíveis. Em vez disso, o que eu sugeriria é , se formos para nossa base aérea e eu as fechasse para não confundir as coisas, queremos clicar duas vezes e abrir a classe base do avião na qual estamos trabalhando para garantir que você não excluiu a classe base do avião Então, com a base do avião ainda aqui, não queríamos nos livrar dessa. O que queremos fazer é realmente usar as classes existentes e simplesmente mover as coisas para onde precisamos. Então, a primeira coisa é focar em nossa nomenclatura. Se focarmos no jogador em primeiro lugar, vou renomeá-lo para BP, sublinhando E é por isso que precisávamos excluir essas outras classes para não termos conflitos de nomenclatura O nome da classe estava bom, mas podemos fazer algo bem inteligente aqui para usar o que já temos nessa classe. E faremos o mesmo com nosso inimigo. Então, vamos pegar esse e chamá-lo BP underscore plain enemy E então, se clicarmos duas vezes para abrir o player do plano de sublinhado da BP, podemos começar a fazer nossas alterações Então, o que achei que seria útil saber é que, na verdade, existe uma maneira muito legal mudarmos o que essa classe está classificando como pai Então, no momento, podemos ver a classe principal como peão. Se voltarmos aqui para as configurações da classe e depois voltarmos ao painel de detalhes, podemos ver que temos a classe principal aqui. O menu suspenso está configurado para peão. Se procurarmos por avião, podemos mudar isso agora herdar da base do plano de sublinhado da BP E essa é, na verdade, uma ótima maneira de refatorar as coisas. Um dos motivos é que ele nos fornecerá erros e avisos sobre códigos que podem estar duplicados E nós meio que já podemos ver isso. Então, se olharmos para o lado esquerdo, podemos ver que temos duas malhas estáticas Qualquer coisa aqui que diga Editar em Blueprint ou Editar em C plus, se você estiver trabalhando em um projeto C plus, é uma indicação de que isso é herdado de uma classe base Então, quando você vê isso, não podemos entrar. Não podemos pegar os herdados e excluí-los, então eles estão presos aqui Então, o que queremos fazer é pegar nosso sublinhado zero da malha estática Não precisamos de duas malhas diferentes para nosso avião e podemos excluir essa, então vamos excluí-la aqui A outra coisa que podemos ver aqui é que temos algo chamado velocidade de movimento com sublinhado zero nas variáveis Se escrevermos, clique aqui, podemos acessar as referências e encontrar todos os membros atuais da classe. Se clicarmos duas vezes neste, isso nos levará diretamente para onde está. Então, como mencionei, é uma boa maneira rápida arrumar as coisas, porque podemos simplesmente usar esses atalhos para pular e encontrar as coisas restantes das quais talvez precisemos nos livrar E, novamente, a razão pela qual isso recebeu um sublinhado zero é porque sabemos que temos algo chamado velocidade de movimento na classe base e não podemos ter a mesma variável, mesmo que esteja em uma versão secundária dessa classe Então, faremos a mesma coisa novamente. Vamos deletar esse. Vamos simplesmente deletar a velocidade de movimento. Isso está apenas nos dizendo que estamos usando isso no momento, mas está tudo bem porque sabemos onde está. E então o que queremos fazer aqui é partir daqui e procurar a velocidade de movimento. E podemos ver aqui que queremos obter a variável de velocidade de movimento, e essa é a da nossa classe base, a classe de emparelhamento E lá vamos nós. Então é basicamente isso. Essa é a aula meio arrumada e pronta para começar. Então, definitivamente poderíamos deixá-lo aqui, mas há mais algumas coisas que podemos usar da classe principal. Portanto, a primeira coisa que sempre queremos considerar é o início do jogo, e precisamos fazer essencialmente em todas as nossas funções. Mas para começar nosso jogo inicial, vamos clicar com o botão direito do mouse no nó e queremos encontrar essa opção aqui para adicionar uma chamada à função principal. E queremos conectar isso entre nossa execução atual e a funcionalidade que já estamos chamando. Isso apenas garante que a lógica do início do jogo dos pais também seja chamada quando começarmos a jogar, que significa que, se tivéssemos novamente alguma lógica universal que quiséssemos fazer na classe principal, ela também será chamada. Caso contrário, isso só será chamado sozinho e ignoraremos a versão dos pais. Queremos fazer a mesma coisa com o evento. Vamos escrever, clicar nisso, adicionar chamada à função principal e, em seguida, conectar tudo. Incluindo os segundos Delta, talvez precisemos mover algumas coisas por aqui. E então podemos simplesmente conectar isso aqui. E, novamente, arrume as coisas se quiser. Tente ajudar a visualizar isso para você, a funcionalidade principal será chamada primeiro Então, por exemplo, quando nosso jogador for criado pela primeira vez, ele automaticamente fará com que seu evento início de jogo seja chamado uma vez e, em seguida, enviaremos imediatamente uma mensagem para realmente dar uma olhada na versão principal e ver se algo está acontecendo para começar a jogar. Navegue até aqui. Podemos abrir o blueprint principal com esse atalho aqui, e podemos começar a jogar aqui, e podemos ver que não há código real no momento se fôssemos fazer algo como tirar No entanto, se fôssemos fazer algo como tirar uma corda impressa daqui, diríamos que os pais começassem e a manteríamos na tela por um momento. O que aconteceria agora é quando pressionamos Play. Veremos que o início dos pais está impresso na parte superior. Assim, podemos confirmar que nossa lógica original, a lógica universal, está, de fato, sendo chamada. Agora, o problema, é claro, é se adicionarmos isso aos inimigos, então, se entrarmos na classe de inimigos simples, entraremos no início do jogo. Nós vamos querer fazer a mesma coisa. Vamos clicar com o botão direito do mouse, adicionar uma chamada para os pais e conectá-la aqui. Agora, como temos três inimigos e um jogador, veremos essa mensagem quatro vezes porque todos estão chamando a mesma função. Obviamente, precisamos fazer a mesma alteração nas configurações da classe inimiga. Mude isso de peão para base simples. OK. Então, estamos fazendo a mesma coisa. Estamos apenas reparando o que essa classe está herdando Clique em compilar. Então, todos os quatro estão seguindo o mesmo processo. Agora, tudo bem, nesse caso, mas é aqui que você deve ter cuidado e começar a se certificar de que está considerando o que está implementando. Então, isso e não faria sentido se essa mensagem dissesse algo como, se fosse específico do que o jogador deveria estar fazendo, como gritar, eu sou o jogador Se clicarmos em compilar, isso significa o player do avião, chamaremos isso, o que é perfeitamente normal Mas então, todos os inimigos. Então, todos os três inimigos também estão dizendo: “Eu sou o jogador”, o que é um pouco confuso Portanto, é aqui que você precisa ter cuidado com a herança. E é por isso que continuo dizendo que queremos nossa lógica universal aqui. Qualquer coisa que esteja relacionada apenas a ser um plano geral está perfeitamente bem. Então, se todo avião tivesse que se anunciar e dizer: “ Eu sou um avião”, tudo bem porque todos os quatro são, de fato, aviões. Como podemos ver, não gostaríamos de nenhum código na classe base relacionado especificamente ao jogador. Então, espero que isso faça sentido, e possamos começar a ver como podemos usar a herança e como podemos compartilhar nossos recursos, componentes e lógica entre E é assim que vamos lidar com coisas como destruição. Podemos fazer com que os efeitos de partículas, todos os efeitos sonoros sejam reproduzidos na classe principal, porque isso não é específico de nenhum plano Todos eles precisam ser destruídos de alguma forma. Mas coisas como o movimento, que são um pouco únicas, vamos lidar com isso nas aulas para crianças. De volta ao player normal. Primeiro de tudo, vamos terminar essa . Uma maneira muito rápida de pegar o código, que sabemos que já está funcionando. Como mencionei, tudo o que realmente queremos fazer é garantir que não tenhamos isso espalhado e que possamos usar essa função que criamos há pouco tempo Então, se pegarmos tudo relacionado ao movimento, então esses serão esses nós aqui, o cálculo aqui, eu estou apenas segurando a tecla Shift e arrastando e , em seguida, a localização do ator aqui Isso está relacionado apenas à rotação, então vamos deixar essa por enquanto. O que queremos fazer é pressionar Control e X para cortar e clicar aqui para substituir a função de movimento da alça Então, queremos a função que criamos anteriormente, esse espaço vazio. E então vamos pressionar o controle V aqui e vamos conectar tudo de volta. Assim, podemos garantir que nossa função de movimento sempre seja chamada porque estamos chamando nosso evento. E se o movimento estiver ativado, o movimento da alça também será chamado a partir desse evento. Então, novamente, só precisamos chamar essa função uma vez aqui, e podemos fazer uso dessa chamada de função em nossas classes filhas. Mudamos isso e vou voltar ao gráfico de eventos. Vamos mover isso para trás, por enquanto, a rotação, e vamos conectar isso de volta. E apenas testando à medida que avançamos, como mencionei, isso é mais para mostrar como você pode refatorar o código sozinho, se necessário E esse é um processo muito comum. Só queremos testar esses pequenos passos à medida que avançamos, e ainda devemos ter o movimento ativado. Então, se algo está quebrado, deixe-me verificar o que pode ser. Se o movimento estiver ativado, se isso for verdade, chamaremos nossos eventos Temos nosso movimento de alavanca aqui, velocidade de movimento. Acabei de perceber que temos nossa nova variável de velocidade de movimento na classe base, mas não atribuímos um valor a ela. Então, se pegarmos nossas configurações de classe aqui, isso realmente nos dará acesso às configurações da classe quando selecionarmos esse elemento superior aqui ou o padrão da classe Podemos ver que os padrões da classe têm as variáveis aqui, e podemos ver nossa velocidade de movimento, e acho que estava configurando isso para 1.000 no player. Então, vamos atrasar isso. E então devemos ser capazes apertar play e nos movimentar. Então, obtemos o mesmo movimento, obtemos a mesma rotação. Tudo parece o mesmo. Não alteramos a funcionalidade. Acabamos de arrumar nosso gráfico e onde as coisas são tratadas Então, estamos garantindo que isso seja chamado se e quando quisermos , e outro benefício muito interessante agora é que podemos entrar Poderíamos desativar o movimento ativado, para que o movimento não seja mais ativado. Podemos apertar play e agora não podemos mover o avião. Mas é claro que isso interrompe a rotação porque agora estamos multiplicando por um valor que realmente não faz nada Mas você pode ver que a lógica é que estamos lidando com as coisas da maneira que queremos que elas funcionem. E tudo isso agora é tratado na classe base em relação aos estados de movimento ativado e desativado, e estamos apenas aproveitando isso na versão para jogadores dessa Portanto, certifique-se de clicar aqui. Vamos garantir que movimento esteja ativado no momento. Vamos alternar isso no código um pouco mais tarde, quando chegarmos à animação Lembre-se de que eu disse que não adicionaremos coisas como rotação ou física falsa e coisas da classe inimiga, é por isso que não estamos reutilizando exatamente o código de movimento Outra coisa que os inimigos não terão é a lógica de rotação real que temos aqui por esse motivo. Algo que poderíamos fazer, no entanto, para manter as convenções de nomenclatura e o estilo geral iguais Tem outra dica que eu queria mostrar. Podemos pegar todos esses nós pressionando Shift Select para capturar esses nós. E então, se clicarmos com o botão direito do mouse em qualquer um dos nós que selecionamos aqui, podemos optar por reduzir isso para uma função própria. E vamos chamar isso de “um”. Você provavelmente pode adivinhar. Vamos chamar isso de rotação de uma alça. Bom e óbvio. Se precisarmos nos aprofundar nisso e começar a ler nosso código, nisso e começar a ler nosso código, viremos do festival da base de aviões e podemos ver que, se o evento continuar, se tivermos o movimento ativado, manipule o movimento e isso sairá da classe base Então, uma vez feito isso, isso nos levará de volta à nossa classe infantil. Então, isso já foi resolvido. O pino de execução será chamado e, em seguida, começaremos a chamá-lo. Então, estamos lidando com o movimento se o movimento estiver ativado, e então estamos lidando com a rotação, novamente, se o movimento estiver ativado. Exatamente os mesmos resultados se pressionarmos play, nada mudou. Estamos apenas tornando isso muito mais legível e sustentável Estamos nos livrando desse código de espaguete ou até mesmo do potencial de isso acontecer aqui porque temos controle total de nossa base de código e de como queríamos que Estamos fazendo uso da herança, então estamos economizando muito tempo ao adicionar novos recursos No momento, isso pode parecer um trabalho árduo, mas definitivamente economizaria muito tempo a longo prazo, entendendo o que isso está fazendo e como usá-lo. Quando estivermos aqui, se você estiver dentro da base do avião, se estiver acompanhando exatamente, podemos nos livrar dessa mensagem descrevendo o que é a classe Vamos nos livrar desse. Ele compila em O inimigo partirá por enquanto e verifique se tudo está salvo na classe do jogador, e essa é a refatoração do jogador concluída Então você pode ver que não foi realmente tão doloroso. Demorei um pouco mais só porque queria explicar esses conceitos e torná-los claros à medida que avançávamos. Se eu estivesse fazendo isso sozinho, provavelmente teria sido uma tarefa de 1 minuto. Portanto, mesmo refatorar e reconsiderar completamente como a estrutura das classes é tratada realmente não precisa demorar muito, especialmente se você está pensando no início do desenvolvimento, especialmente se você está pensando no início do desenvolvimento, é por isso que estou tentando enfatizar isso à Tente fazer essas escolhas com antecedência, e é a diferença de ter uma refatoração de 1 minuto para uma refatoração de 1 hora Se você estiver testando seu código e algo estiver quebrado ou não estiver funcionando, verifique se todas as chamadas dos seus pais estão conectadas. Então, esses pais ligam aqui, os nós laranja são conectados e chamados no início do jogo, na marcação do evento e assim por diante. Da mesma forma, verifique se o movimento está ativado aqui na classe base e, o mais importante, por meio desse valor aqui em cima, como acabei de mostrar, apenas algumas pegadinhas, nas quais imagino que algumas pessoas possam cair Então, basta verificar as coisas que estamos mudando. Para o próximo tópico, é claro, vamos abordar a mesma coisa, mas para o inimigo , isso deve levar um pouco menos de tempo. Agora vimos como fazer isso aqui. 15. 14 — Refatoração do inimigo: Refatorando o inimigo. Já fizemos isso uma vez. Deve ir um pouco mais rápido. Obviamente, se você ainda não tem isso aberto, vamos nos certificar de abrir a classe inimiga simples. Verifique aqui, se você ainda não fez a alteração , se redefinimos a classe principal aqui para a base do plano de sublinhado da BP Lembre-se de que podemos fazer isso por meio das configurações da classe e do menu suspenso aqui. Novamente , as mesmas coisas que com o jogador. Vamos excluir a malha estática, o que nos causará um pequeno problema aqui. Vamos apenas dizer: Tudo bem, então clicaremos em sim. Isso me levou direto ao ponto em que está o problema, ou seja, vinculamos função de impacto do componente anterior, aquela verificação de colisão, à malha estática original Na verdade, isso não é um problema porque queríamos corrigir isso de qualquer maneira. Não queremos usar a malha como colisor em vez disso, vamos pegar o componente esférico aqui, então vamos pegar este e queremos fazer a mesma coisa novamente Então, no lado direito do painel de detalhes, simplesmente soltamos isso. Vamos encontrar a função do quadril no componente on e criar uma ligação para ela. E isso é tudo que isso está fazendo. É apenas vincular sempre que ocorre uma ação , está vinculando essa função para ser chamada. Então, podemos excluir este, conectar as mesmas coisas, então pino de execução e pino de ator, e essa é a parte inicial do problema resolvido. Então, vou entrar na janela de exibição rapidamente. Vamos pegar a malha estática e queremos ter certeza de que estamos atualizando o material. Então, novamente, no elemento zero aqui, esse é o que controla o corpo do avião. Vamos anotar isso e agora podemos encontrar outro material que você pode ter feito para seu inimigo, que para mim é apenas MI underscore plane enemy Selecione esse e estamos praticamente de volta onde estávamos. A mesma coisa com a velocidade de movimento também. Queremos clicar com o botão direito do mouse sobre isso, encontrar as referências do aluno apenas para ter certeza de nos livrarmos de todas elas. Podemos clicar duas vezes em um deles e ver onde eles estão sendo usados. Podemos ver que temos alguns deles para garantir que não percamos nenhum quando estamos tentando conectar as coisas novamente. Vou clicar com o botão direito do mouse no gráfico de eventos aqui embaixo, pesquisar a velocidade de movimento e obteremos a variável de velocidade de movimento aqui, aquela que foi criada em nossa classe principal. Encaixe isso aqui, duplique isso, coloque isso aqui embaixo, remova isso só para arrumar as coisas um pouco, e clique duas vezes no final , que está aqui E, novamente, vamos clicar com o botão direito do mouse e pesquisar a velocidade de movimento. Vamos definir a velocidade de movimento aqui e, em seguida, conectá-la. Livre-se disso e voltaremos para onde estamos. Agora, há uma opção que eu não queria mencionar porque achei um pouco complicada. Na verdade, na versão atual, isso simplesmente não parece funcionar. Mas algo que pode ser útil se eles corrigirem isso no futuro é que, no passado, pudemos clicar com o botão direito do mouse na variável. Podemos selecionar aqui para substituir as referências. O que estou perdendo no momento é que não sei para onde foram esses recursos. Normalmente, você pode soltar isso e poderíamos ter encontrado a variável de velocidade de movimento criada na classe principal. Por qualquer motivo, eu só posso acessar diretamente as variáveis do ator e do peão, não a base real de reivindicações do sublinhado da BP, embora eu devesse ser Mas só para dizer que, por esses motivos, talvez precisemos fazer isso da maneira um pouco mais manual que acabamos de remover, lembre-se de se livrar do sublinhado de velocidade de movimento zero Não devemos mais usar isso e, em seguida, basta clicar em compilar para garantir que tudo tenha sido concluído O mesmo com o jogador. Agora que os temos na classe inimiga, só queríamos verificar novamente. Eu já segui esse caminho enquanto fazíamos o conteúdo do jogador. Se você decidiu não entrar na classe inimiga estou focado apenas na classe de jogador simples. Em seguida, verifique se você também tem o início do jogo, chamada dos pais e a substituição eventI da chamada dos pais Então, vamos clicar em R aqui. Vamos fazer a chamada de adição à função principal e, novamente, apenas garantir que as conectemos à medida que avançamos Para a lógica do movimento, faremos a mesma coisa novamente. Então, na verdade, queremos que a mesma lógica de movimento aconteça. Nós podemos pegar tudo isso. Nada realmente vai mudar. Podemos pegá-los, então basta selecionar Shift para pegá-los. Queremos pressionar o controle em X para cortar todos os nós daqui. Vamos substituir e substituir a função movimento da alça Depois de fazermos qualquer coisa que precise acontecer na função principal, vamos colá-las aqui e depois garantir que nosso movimento seja chamado. Feito isso, isso me lembrou que também poderíamos melhorar outra coisa aqui Então, queremos ter certeza de que com a sobreposição que estávamos fazendo, anteriormente estávamos apenas ligando para destroy actor e deixando uma mensagem aqui Podemos trazer nossa função de lidar com a morte, colocá-la aqui e substituí-la pela função de destruição. Então, vamos nos livrar de Destroy. Nós temos tudo sob controle. O que talvez queiramos fazer é realmente entrar aqui. Vamos deixar um comentário para nós mesmos. Então, isso foi tirado. Se clicarmos duas vezes sobre isso, isso nos levará para a base do avião. Então, agora estamos na classe dos pais. Podemos partir daqui, e algo que sempre vamos querer fazer no final é chamado de ator de destruição. Uma coisa que talvez queiramos fazer é usar os comentários para facilitar o rastreamento das coisas. Então, se pressionarmos C para colocar um comentário aqui, eu gosto de deixar para mim esse tipo de anotações posticas, quase Podemos dizer algo como implementar o efeito pré-morte. Então, o que acontece antes de destruirmos nosso ator? Nós vamos fazer isso aqui mesmo. Isso torna tudo muito fácil porque você pode pressionar Control em F em qualquer classe e pesquisar por Do. Clique duas vezes sobre isso. E onde quer que você esteja em sua classe, se ainda tiver muitos comentários para fazer, você pode ir rapidamente até eles e ver no que pode trabalhar. Também podemos ir para o lado direito. Podemos dar uma cor diferente para que se destaque um pouco. Depende totalmente de você como você gostaria de lidar com isso. Mas, como mencionei, é uma ótima maneira encontrar rapidamente os recursos que talvez ainda não estejam totalmente prontos para serem implementados porque não estamos tocando nessas partes do sistema, mas sei que precisarei voltar aqui e fazer isso em algum momento Então, quando voltarmos para atualizar isso mais tarde, é assim que você realmente deve se concentrar em seu fluxo de trabalho. Isso realmente não fez nada por nós agora. O que isso significa é que, quando voltarmos para adicionar efeitos e coisas do tipo mais tarde, não precisamos voltar e alterar nosso código inimigo. Agora está pronto para ser usado. continuar desenvolvendo todo o projeto, e isso será contabilizado automaticamente quando atualizarmos os recursos aqui O resto da colisão ainda é o mesmo. Isso ainda vai ser basicamente o que precisamos fazer aqui. Você pode substituir isso por um comentário, outro para fazer um comentário, se quiser, mas, novamente, não temos acesso ao sistema de saúde, então precisamos de algo para nos lembrar voltar aqui, e essa string de impressão está boa. Só queremos verificar se tudo isso está funcionando, então voltaremos ao modo de jogo, garantindo que os inimigos e o jogador ainda estejam se movendo. Pretendido, e tudo isso é muito bom. Eles ainda estão pulando nas paredes. Eles ainda estão seguindo sua direção aleatória, velocidade aleatória, ricocheteando um no outro, e podemos voltar e mudar isso, dependendo de como achamos que o jogo deveria Mas acho que com isso feito, agora temos a paridade de comportamento Tudo funciona como antes, mas fazendo uso da herança adequada É só uma rápida recapitulação, agora que terminamos nossa refatoração, passando a usar a herança descobrir o que isso O principal será que compartilhamos a configuração de colisão Podemos configurar essa esfera uma vez e ela funcionará nas duas classes que fazem uso dela. Temos o tratamento compartilhado da morte. Então, novamente, quando adicionarmos coisas como explosivos e sons, ambas as classes poderão usar Podemos substituir o efeito, se necessário, mas não precisamos fazer nenhuma alteração nosso código base agora Temos a opção de ativar a lógica de movimento compartilhada, então, quando adicionarmos as animações, esse movimento ativado será válido para cenas cortadas tanto para o jogador quanto para o inimigo Temos variáveis compartilhadas, como a velocidade de movimento. Ela existe quando não temos duplicações ou várias versões delas em toda a classe Talvez eu veja meu exagero no momento apenas nessas duas classes diferentes, mas estamos prestes a adicionar coisas como saúde, projéteis, efeitos esportivos e tudo mais Agora teremos um pool de recursos compartilhado para extrair de onde as coisas são relevantes para usar a mesma coisa em vez de duplicá-la Uma coisa que acabou de vir à mente é que poderíamos fazer essas atualizações de esfera agora. Como mencionei, o tipo geral de abordagem que as pessoas adotam com esse tipo de jogo é para o jogador. Queremos que a esfera talvez seja um pouco menor do que o esperado. Então, isso pode realmente estar bem. Poderíamos potencialmente aumentar um pouco o raio da esfera No momento, podemos ver que está realmente dentro do corpo. É tão pequeno que não conseguiríamos vê-lo. Então, o projétil vai voar completamente por toda a envergadura e pela maior parte do corpo Isso, como mencionei, é apenas para fazer o jogador se sinta um pouco melhor do que é. Se eles pensarem em seus olhos que uma bala quase os errou, mas na verdade, ela os atingiu. Eles vão se sentir como se esquivassem disso. E o que não queremos é que aconteça de outra forma, onde eles sintam que deveriam ter se esquivado de alguma coisa, mesmo que claramente não o tivessem feito, e se sintam enganados ao sentirem esse dano extra em suas mentes Com a esfera selecionada, porém, queremos encontrar o raio da esfera aqui, e podemos definir isso para algo como 50, e você verá onde isso entra em jogo Então, agora, essa é a área que o jogador estaria sofrendo dano. Então, talvez eu reduza isso um pouco, então é puramente o corpo, algo como 45, e acho que provavelmente é a margem de manobra que queremos dar a eles Se clicarmos em compilar e depois voltarmos para a classe inimiga, a mesma coisa Vamos entrar no mirante, pegar a esfera, mas acho que desta vez, o que eu poderia fazer é torná-la algo como 64 ou dobrá-la E, na verdade, talvez até seja um pouco pequeno demais, então vamos fazer algo como 70. Então, novamente, vai parecer o jogador sentirá que está atirando muito melhor que, toda vez que atira, na verdade está atingindo o inimigo exatamente como planejou, quando, na verdade, perderá o corpo, mas vamos pegar isso para eles e fazer com que pegar isso para eles e fazer sintam que estão fazendo melhores no jogo do que poderiam ser. Obviamente, queremos equilibrar isso. Não queremos facilitar demais, mas você pode ver que é bom e fácil ajustar essas coisas de qualquer maneira Então é assim que a herança é configurada. Ambas as classes estão funcionando, ambas herdam da base do avião Em seguida, podemos passar a adicionar a saúde e os danos. E será aí que você realmente começará a ver os benefícios de aproveitar esse tempo antes da implementação para configurar a herança. 16. 15 — Sistema de saúde: É hora de adicionar saúde e danos. Já temos nossa classe base configurada para compartilhar os dados importantes, então vamos direto para a base do plano de sublinhado da BP Aqui, precisaremos de duas variáveis diferentes. Queremos monitorar nossa saúde atual, a saúde que temos atualmente e nossa saúde máxima. Podemos fazer isso com o uso de flutuadores, então vou pegar a velocidade de movimento, pressionar o controle, na verdade, duplicá-la uma vez e chamá-la de saúde atual Duplique-o uma segunda vez e chamaremos esse de Max Health. Se clicarmos em compilar, obterei o máximo de saúde e definirei isso para um padrão de 100 Podemos deixar a saúde atual vazia. Em vez disso, o que estamos fazendo é, no início do jogo, colocar nossa saúde atual no pino de execução aqui, e queremos pegar nossa saúde atual e defini-la como nossa saúde máxima. Sem erros humanos. Toda vez que começarmos a jogar, sempre nos certificaremos de começar com saúde total. Portanto, uma maneira simples e agradável de garantir que não tenhamos nada de errado com nosso sistema de saúde. Mais uma vez, só um lembrete. É por isso que é realmente importante. Quando clicarmos em compilar e salvar, volte para o player normal e verifique se você tem o controle para começar a jogar, e o mesmo para o inimigo Então é aqui que isso se torna importante, porque queremos garantir que ambas as classes inicializem sua saúde com qualquer que seja sua saúde máxima Com isso confirmado, também podemos implementar nosso manipulador de danos. Isso é muito simples. O RL Engine possui um sistema de mensagens integrado especificamente para lidar com danos Se clicarmos no gráfico de eventos, precisaremos pesquisar um evento chamado qualquer dano. Então é esse aqui, o evento, qualquer dano. E isso será chamado sempre que enviarmos uma mensagem de outro ator, seja um projétil, um explosivo impactando o avião ou a classe inimiga, podemos enviar uma mensagem dizendo: Ei, você foi danificado Quando essa mensagem for enviada e recebida aqui, essa chamada de evento ou função será feita. E quando isso acontece, tudo o que queremos fazer é definir nossa saúde atual, então vamos arrastar isso para o pentágono de execução Faremos disso nosso inferno atual, então pegaremos a saúde atual pela segunda vez, controlaremos e arrastaremos isso para o gráfico para ler o valor, e isso resultará em nosso dano negativo. Então, o inferno atual menos um valor aqui, que será o dano que estamos transmitindo, então isso será algo que colocaremos na chamada da outra classe O resultado desse cálculo será nosso valor de saúde. Uma coisa que normalmente é recomendada para esse tipo de cálculo é evitar que as coisas fiquem um pouco complicadas ou estranhas Não queremos permitir danos ou, se também implementamos a cura, não queremos permitir que esses valores nos levem além do nosso limite máximo ou mínimo Então, podemos usar algo chamado grampo. Vamos puxar esse pino aqui e procuraremos a braçadeira. Queremos a opção de fixação flutuante, que está um pouco aqui em cima. Então, a braçadeira flutua E vamos inserir o resultado dessa fixação em nosso pino aqui Então, podemos ver o que isso nos permite fazer. Podemos pegar nosso valor mínimo. Portanto, a quantidade mínima de saúde que devemos ter é zero. E a quantidade máxima de saúde que podemos ter será nosso valor máximo de saúde. Tão bonito e simples. Isso significa que, se adicionarmos algo como kits de saúde, quando você pega um desses, não poderá ultrapassar a saúde máxima com a qual começou. Portanto, ele sempre manterá os resultados desse cálculo dentro desse intervalo. Depois de confirmarmos que a configuração da saúde foi feita corretamente e não conseguirmos errar, faremos nossa verificação para ver se o dano que acabamos de sofrer é suficiente para nos destruir. Então, vamos retirar nosso pino de execução aqui. Vamos procurar uma filial. Nosso verdadeiro falso controle de fluxo aqui. E tudo o que queremos fazer é recuperar nosso valor de saúde atual novamente, então controle e arraste isso para dentro. Veja se isso é menor que. Então, vamos procurar o operador menor que aqui. E o que vou fazer é realmente verificar se isso é menor ou igual a um determinado número. Insira isso na ramificação aqui, a booleana, e agora temos uma verificação dizendo que, se nossa saúde atual for menor ou igual a zero, podemos lidar com nossa chamada da função de morte ou da função de tratamento de morte Pergunte por que estamos usando menos down em igual a, especialmente porque acabamos de restringir isso para garantir que nunca fique abaixo de zero E isso é apenas uma espécie de hábito de segurança. Se algo causar mais danos do que o inferno restante, ou se tivermos alguma estranheza de ponto flutuante, ou mesmo se refatorarmos o código novamente mais tarde e decidirmos não corrigir isso, quero ter certeza de que essa verificação sempre será relevante para garantir Então, por exemplo, se pegarmos essa pinça, se tivermos cinco pontos de vida e sofrermos mais dez de dano, obviamente, teremos menos cinco, o que significa que, se verificarmos apenas zero , algo que tenha sofrido mais dano do que deveria evitaria ser morto Com isso feito, porém, de nossa filial aqui, podemos lidar com a morte. E se isso for verdade, podemos simplesmente conectar isso. É isso que agora começará a lidar com todas as funcionalidades de morte qualquer um dos aviões que você possa se sentir tentado a fabricar e, é claro, dos dois que já temos Handle Death já tem a função destruída e, como mencionei, voltaremos aqui mais tarde para adicionar coisas como explosões, efeitos sonoros e todas as coisas divertidas e suculentas que queremos colocar em nosso jogo Então, para realmente começar a usar o sistema de danos, já temos algo pronto para testar pelo menos parte de como essa estrutura funcionará dentro do nosso inimigo. Então, se voltarmos para a classe inimiga, essa parte aqui, que está imprimindo nossa sequência de caracteres há muito tempo, podemos finalmente removê-la Em vez disso, o que queremos é pegar nosso ator de sucesso, então controlaremos o arrasto para o gráfico. Vamos usar o outro ator e estamos procurando aquela mensagem global que mencionei um pouco antes, a de aplicar dano. Então, podemos ver aqui que aplicamos danos. Isso apenas faz uma ligação para qualquer ator com quem possa se comunicar. Nesse caso, será aquele em que acabamos de entrar . Vamos conectar isso aqui mesmo, então pegaremos nossos pinos de execução, verificaremos se estão todos conectados , tiraremos isso do caminho e queremos aplicar uma certa quantidade de dano ao jogador Acho que, para os inimigos, vou dar saúde a essa metade dos jogadores. Eu sei que o jogador terá 100 curas. Vamos definir isso para 50, e isso significa que o jogador pode receber dois golpes de um inimigo para não querer pular nele com muita frequência. Não será uma maneira rápida e limpa de ganhar pontos extras simplesmente voando todos os inimigos. Agora, isso me lembra. Outra coisa que podemos fazer com nossas variáveis herdadas é selecionar o inimigo, por exemplo, e obter os detalhes da classe aqui, no lado direito, queremos ter certeza de que a saúde do inimigo provavelmente será diferente da saúde do jogador Assim, poderíamos definir a saúde do inimigo para 50 e, no jogador, verificaremos se o padrão deve ser 100 Certifique-se de que a saúde do jogador esteja definida como 100. Então, novamente, uma boa maneira fácil de definir o valor da saúde apenas uma vez e lidar com isso na classe principal, tanto para o dano sofrido quanto para a saúde fornecida aqui, porque eles são baseados em variáveis que existirão em todas as classes. E então, nas classes secundárias, tudo o que precisamos fazer é ajustar essas variáveis no editor se quisermos mudar o tipo geral de marcação do nosso jogo E, como mencionei, porque já configuramos isso de uma certa forma, agora significa que temos o nome de morte. Não precisamos voltar e tocar nisso. Precisávamos fazer uma pequena mudança: o lado da classe inimiga não precisava ser contabilizado e tudo continuará funcionando como estava Uma coisa que quero mostrar rapidamente, só porque esse é outro daqueles lugares realmente claros você pode ter se sentido tentado a adotar uma abordagem diferente para lidar com a morte do inimigo, é que poderíamos desligá-lo por enquanto Outra coisa que você pode fazer é duplicar nossa função de aplicar dano Poderíamos inserir isso aqui porque o principal é que, quando atingimos o avião do jogador, sabemos que a classe inimiga precisa se danificar, essencialmente. O que poderíamos fazer é pegar nosso valor máximo de saúde. Então, podemos pesquisar por MAXel e inserir isso aqui. E então, o ator danificado, poderíamos basicamente aplicar dano a nós mesmos. Então, se retirarmos do ator danificado aqui e procurarmos por uma célula, obteremos essa opção integrada na funcionalidade que eu queria apresentar, obtendo uma referência a si mesmo. Então, basicamente , é um pouco estranho. Isso basicamente encontrará uma referência a si mesmo, que é encontrada aqui. Ele chamará por si só a mensagem de aplicar dano, que obviamente será captada na classe base, pois é aí que temos o caso de algum dano ser causado. E porque estamos transmitindo o máximo de saúde, e isso é apenas uma questão de segurança. Mais tarde, decidi que, na verdade, a saúde do inimigo aos 50 estava muito baixa, e entrei e mudei para 75. Obviamente, o que não queremos fazer é ter esse 50 codificado, porque qualquer alteração que fizermos em uma base mais ampla do que apenas esse nó aqui seria meio esquecida e perdida Outra forma, novamente, é tentar pensar em como você estrutura seu código, no uso de variáveis, principalmente no tipo de preparação para o futuro , para que você não precise trabalhar mais no futuro A principal coisa com os programadores é que somos muito preguiçosos. Quanto menos trabalho tivermos que fazer, melhor, evitando voltar ao nosso código e alterar variáveis em todos os lugares. Se pudermos configurar algo assim, posso alterar a saúde máxima para qualquer coisa. Eu poderia diminuí-lo, eu poderia aumentá-lo. Essa função sempre funcionará. Como mencionei, porém, ele simplesmente não é lido de forma muito clara. Demora um pouco mais para descobrir por que temos um dano aplicado, outro aqui e quais são esses diferentes atores. Acho que faz mais sentido se vamos criar um tipo completo de inimigo ao estilo kamikaze, podemos simplesmente conectá-los e isso torna tudo muito mais claro Então, vamos aplicar dano ao que fizemos, apenas depois de fazer isso, vamos aplicar dano a nós mesmos. E lembre-se, isso é realmente seguro porque estamos olhando aqui embaixo, verificando se o ator de sucesso é o que o jogador humano está controlando no momento, e somente se isso for verdade, faremos isso. Portanto, isso não causará danos às paredes, aos projéteis ou a outros inimigos Tudo isso será contabilizado aqui embaixo. Portanto, essa é uma maneira agradável, fácil e segura de estruturar danos por impacto. Algo que eu realmente não mencionei, mas também tenha em mente que a ordem de operação é muito importante. Assim que você pensa sobre isso, se você nunca pensou nisso antes, fica realmente óbvio. É algo que as pessoas sentem falta. Se lidarmos com a morte primeiro, então poderíamos jogar isso para o outro lado também. Se conectarmos isso aqui, solte-os e mova isso. Apenas um exemplo muito rápido, conecte-o novamente. E isso é só porque eu já vi isso acontecer antes. Os alunos não sabiam ao certo por que certas funções não estavam sendo convocadas quando esperavam. Às vezes, também pode estar no sistema. Alguns sistemas podem funcionar, outros podem não, dependendo da rapidez com que a iteração do ticket e coisas assim acontecerão Mas, basicamente, se você pensar no que está acontecendo aqui, se atingirmos o player e chamarmos handle death primeiro, isso será entrar na função principal, chamando destroy e, potencialmente, se isso for imediatamente adicionado à coleta de lixo e apagado da memória, essa classe não Isso significa que não vai sair daqui, voltar para essa função e causar danos ao jogador Portanto, você pode acabar com um jogo em que o jogador simplesmente nunca receba danos de impacto. Portanto, tenha cuidado com esse tipo de coisa. E, novamente, é muito comum que as pessoas já tenham lidado com o lado mortal das funcionalidades e depois voltem e adicionem os efeitos de partículas e o som e depois não saibam imediatamente por que as partículas e os efeitos sonoros não estão sendo os efeitos sonoros não estão É porque sua aula provavelmente está sendo apagada da memória e não existe. Essa função está sendo chamada. Portanto, a ordem de operação também é importante. Controle de fluxo é outra palavra para isso. Esse foi um tipo de exemplo muito simples, mas é uma armadilha fácil de cair se você não estiver prestando atenção suficiente Mesmo que você entenda o conceito, é um erro simples de cometer. Então, com isso, se apenas clicarmos em compilar e salvar, podemos voltar e testar ou clicar em reproduzir O que estamos procurando aqui é garantir que eles ainda se destruam ao atingirem o jogador. E o mais importante, depois de dois golpes como os que vimos lá, eles também estão destruindo o jogador Portanto, nem o jogador nem o inimigo têm um sistema de saúde, tendo em mente que não estamos implementando esse sistema de saúde em cada classe. Estamos fazendo isso apenas uma vez na classe base, e toda essa funcionalidade para calcular a saúde, verificar se a classe está morta e, em seguida, chamar a função está sendo tratada lá Ao analisar isso, acabei de perceber que provavelmente cometi uma pequena de codificação. Isso na verdade nos causará um pequeno problema porque chamamos handle death quando calculamos que a morte seria apropriada, e estamos chamando isso Há uma boa chance de conseguirmos que dois conjuntos de partículas funcionem. Vamos receber uma da chamada de disfunção e, em seguida, uma da chamada de disfunção, que está acontecendo com base na saúde Então, agora que estou analisando meu próprio código, o que acho que deveríamos fazer é, na verdade, a maneira que eu estava tentando usar apenas como um exemplo de aprendizado. Mas se duplicarmos isso novamente, acho que teremos que fazer de outra maneira Então, vamos causar danos a nós mesmos. Então, novamente, vamos retirar o agente de dano. Vamos dizer vender, e vamos colocar isso aqui. Isso só garante que é muito fácil ignorar coisas como essa Sorte que voltamos e demos uma olhada rápida no código. Isso apenas garante que o dano seja aplicado a nós mesmos. Vamos usar o mesmo truque que mencionei há pouco, então Maxel E, novamente, percebo que poderia editar isso do vídeo. Mas como criei todo esse projeto com a intenção de tentar ensinar como pensar em programação, acho que esse é um ótimo exemplo de aprendizado do tipo de coisa que você pode ignorar e como pode facilmente se meter em uma pequena situação que precisa voltar e corrigir Então, isso garantirá que definitivamente nos matemos. Estamos sempre transmitindo a quantidade máxima de saúde que poderíamos ter. fará com que isso seja chamado, que garante que nosso identificador morte seja chamado apenas uma vez, que significa que, quando chegarmos aos efeitos de partículas, aos efeitos sonoros, o chamaremos uma vez aqui e depois tocaremos uma vez aqui Então, essa é a principal coisa que queremos evitar, que eu possa excluí-la. Não lê muito bem. É aqui que você pode querer fazer um comentário apenas para deixar claro. Isso é para o jogador. Isso é para você mesmo garantir que sempre saiamos do jogo depois de bater no jogador Coisa muito simples, coisa muito pequena. Transformei isso em um tópico maior só porque é mais um momento de aprendizado que surgiu acidentalmente Última pequena coisa que podemos fazer enquanto ainda estamos na classe inimiga. Podemos remover o uso de números mágicos. Então, no momento, estamos apenas aplicando 50 de dano ao jogador. Podemos transformar isso em uma variável e chamaremos isso de dano de impacto. Basta verificar se há outros que possamos ter perdido. Acho que foi só essa. Na verdade, nós os temos se você quiser criar uma velocidade de movimento mínima e máxima, porque o inimigo tem a chance dessa randomização Ele compila, salva, volta para o player, confira aqui Acho que não temos tantas variáveis que criamos recentemente, então tudo bem na classe do jogador e também na classe base. Outra coisa que talvez você queira fazer se estiver realmente tentando manter todas essas variáveis organizadas à medida que começa a obter muito mais variáveis, pode ficar um pouco mais difícil descobrir a que elas estão relacionadas Assim, você pode fornecer categorias de variáveis, o que pode ajudar. Então, por exemplo, temos aqui a velocidade atual, a velocidade alvo, a velocidade de interação. Então, esses três estão todos relacionados ao movimento e, em seguida, esses dois estão relacionados à rotação. Então, o que podemos fazer é selecionar uma delas no painel de detalhes, obtemos essa opção aqui para uma categoria e podemos configurá-la para algo como movimento. E então podemos simplesmente arrastar e soltar os outros movimentos na categoria de movimento. Podemos pegar a rotação e talvez possamos dar a ela uma categoria de rotação. mesmo de novo, coloque-os aqui, e então podemos derrubá-los. Facilita um pouco , especialmente quando você tem uma longa lista de variáveis que começam a aparecer em classes maiores Isso significa que você pode navegar muito rapidamente para encontrar todas as coisas relacionadas ao movimento se estiver procurando por um valor muito específico para ajustar e o mesmo para rotação Você pode lutar. Você pode ter uma categoria de booleanos, vetores, o que quiser configurar aqui Exatamente como seu processo de trabalho se adequará melhor ao seu projeto, mas apenas uma ideia rápida. Se você quiser fazer algo entre os tópicos, fique à vontade para fazer uma pausa, fazer uma pequena pausa no acompanhamento e talvez voltar às outras classes e ver como você pode categorizar as coisas na classe base e talvez até na classe inimiga Não vou fazer isso na tela, mas é apenas uma ideia para colocar esses conceitos em prática e informar que esses recursos existem. Com isso feito, porém, nosso sistema de saúde está completo. Já implementamos isso uma vez e está funcionando em todos os lugares. Isso significa que podemos passar para os projéteis. E, novamente, agora podemos simplesmente construir sobre a base que já criamos. Será aí que o combate ficará mais interessante e quando poderemos realmente revidar. 17. 16 — Movimento Melhorado: Lembre-se daquele bug de taxa de quadros que reconhecemos e acabamos de superar É hora de voltar a isso e consertá-lo. Substituiremos o código de movimentação problemático algo pronto para produção Independência adequada da taxa de quadros, estrutura mais limpa e melhor preenchimento. Percebo que antes de começarmos a adicionar coisas sofisticadas, como geradores de atores, projéteis e aprimorar o sistema de danos, enquanto estamos fazendo esse fator enquanto estamos fazendo esse fator e aprimorando o código base, provavelmente deveríamos voltar e garantir que não esqueçamos o movimento e o bug que já conhecemos esqueçamos o movimento e o bug O código ofensivo que precisamos corrigir está em nossa classe de jogador Então, se você ainda não tem isso aberto, vá em frente e abra o BP Underscore plain player No meu caso, vou pressionar o botão do meio do mouse fechar as guias que não usaremos Então, a classe base e a classe inimiga e navegue até a função de movimento da alça logo aqui. Então esse é o código que queremos substituir e melhorar. Agora, a primeira coisa é que, após o movimento da alça principal, queremos clicar e desconectar esse código Algumas pessoas têm opiniões diferentes sobre esse tipo de coisa. Novamente, quero manter o foco na estrutura do código, nas boas práticas e em coisas assim. O que você pode ver, especialmente no código C plus plus, é alguns desenvolvedores podem manter o código antigo que estamos tentando substituir. Talvez coloque isso em um comentário , caso queira vê-lo mais tarde, caso ache que talvez precise recorrer a isso. Isso acaba com um espaço de trabalho desordenado. Talvez você tenha muito mais código em seu C plus do que precisa. Em Blueprints , obviamente, podemos ter muito mais coisas apenas no gráfico do que precisamos E, idealmente, estaríamos usando algo como o Github para controle de origem de qualquer maneira Então, se precisássemos examinar um código antigo, o ideal seria reverter nosso repositório e visualizá-lo por meio do Git ou Perforce ou algo assim Agora, neste caso, vou manter isso apenas por um momento, porque acho que há algumas coisas que podemos simplesmente copiar e colar rapidamente, mas vamos nos livrar totalmente desse código Então, vamos começar este do zero. A primeira coisa que queremos fazer é extrair nosso pino de execução aqui e criar algo chamado sequência. Queremos essa opção aqui mesmo. E se você nunca viu isso antes, as sequências são muito subutilizadas Eles fazem com que nosso projeto seja lido como um código tradicional, ou seja, de cima para baixo, da esquerda para a direita Cada um dos pinos lida com uma tarefa específica, ou pelo menos é assim que devemos pensar em usá-los É muito mais limpo do que a lógica que se estende pelos três monitores, só porque você tem essa longa linha de lógica Só para ressaltar, não estou me exibindo. Isso foi um exagero. Na verdade, eu não tenho três monitores. Existem outros benefícios e motivos pelos quais você pode querer usar isso, mas o principal, voltando às sequências, é que elas são uma maneira muito boa de ajudar a estruturar nosso código e nos ajudar a pensar logicamente, dividindo as coisas essencialmente em etapas Você está dizendo, faça isso, depois faça isso, então faça isso, e você tenta manter tudo um pouco exclusivo para uma determinada tarefa. Então, a primeira coisa que realmente queremos em nossa tarefa é calcular nossa velocidade de movimento alvo. Já estamos fazendo isso aqui, então essa é uma das coisas que podemos pegar. Se pegarmos o código até o nó de velocidade de movimento alvo, pressione Control em X e, em seguida, cole novamente. Portanto, essa será a primeira tarefa que daremos a nós mesmos em nossa sequência. Outra coisa que pode nos ajudar a manter o código um pouco legível é que, se clicarmos duas vezes em um fio, isso nos dará um nó de reinicialização. Podemos mover isso até aqui porque queremos ter certeza de que teremos espaço suficiente, essencialmente para o caminho diferente que estamos seguindo. Agora, uma coisa que vamos mudar é que vamos criar nossa própria interpolação Não usaremos F interp two. Por esse motivo, vamos mudar um pouco dos segundos do Get World Delta. Cara, livre-se desse nodo aqui, da multiplicação. Conecte isso diretamente à velocidade alvo definida e tornaremos essa taxa de quadros independente um pouco mais tarde. Vamos manter isso por perto. Precisaremos disso em apenas um momento. Eles obtêm segundos Delta mundiais. Mas é basicamente isso. Esse é o nosso primeiro passo. Nossa primeira coisa que precisamos fazer é ter uma meta a ser alcançada. Isso então nos alia. Podemos ir até então um. E o que vamos fazer aqui é calcular nossa própria interpelação personalizada Alpha Então, isso vai ficar um pouco matemático, mas será a chave para a independência adequada da taxa de câmbio Vamos continuar, vamos adicionar isso e, em seguida, vou voltar atrás e tentar explicar por que acabamos com um cálculo que temos. Então, a primeira coisa que queremos é nossa velocidade de interação de movimento aqui, então vamos controlar o arrasto para dentro e obter a velocidade de interação de movimento Multiplicaremos isso por nossos segundos Delta, é por isso que ele está disponível há pouco, então teremos nossos segundos Delta do Get world para começar a fazer com que segundos Delta do Get world para começar a nossa taxa de quadros de cálculo seja independente novamente Em seguida, queremos negar ou inverter o cálculo que criamos, então vamos multiplicar aqui Vamos multiplicar o nó e multiplicar isso por menos A partir do nosso cálculo aqui, vamos puxar novamente. Vou pesquisar algo chamado EXP. Este é o valor exponencial, então diz aqui, isso retornará o E exponencial à potência do valor. Então, vamos usar isso. E, finalmente, depois do nosso nó exponencial, vamos puxar a partir daqui e vamos subtrair, então basta pressionar a tecla menos, encontrar, subtrair e subtrair um do cálculo encontrar, subtrair e subtrair um do O importante, antes de esquecermos , é que obviamente não queremos nenhum número mágico, vamos usar o pino final. Vamos promover isso para uma variável e chamaremos isso de MV Alpha Se você estiver criando categorias, talvez queira movê-las para a categoria de movimento. Como, é claro, esse será um movimento específico. Vamos conectar isso ao nosso pino de execução, depois ao primeiro, e agora temos nosso código Alpha pronto para uso. Portanto, essa é nossa interpolação suave que usaremos de uma forma mais manual e intencional em Então, só para focar novamente , o que isso está fazendo é nos dar um menos E a velocidade negativa vezes Delta Essencialmente, isso está fornecendo uma curva de decaimento suave. Essa é a principal razão pela qual precisamos usar a subtração de um no final, pois queremos que ela decaia com o tempo E a razão pela qual precisamos usar uma fórmula como essa é voltar à principal fonte do problema que estamos tendo entre diferentes taxas de quadros e mantendo as taxas de quadros independentes. A função F interp está na verdade, fornecendo uma aproximação linear, e é isso que está quebrando em baixas taxas de Em comparação, se criarmos uma função como essa que podemos usar com uma função larp padrão, essa abordagem exponencial nos fornece interpolação matematicamente correta Então esse era o objetivo principal aqui: na verdade, queremos parar completamente de usar isso. Por fim, lembre-se de que queremos tentar fazer coisas específicas muito exclusivas por linha. Vamos adicionar outro pino e queremos os dois pinos aqui. Vamos partir daqui e queremos fazer a última coisa, que é, na verdade, usar a velocidade atual, fornecendo interpolação a Ainda queremos usar a interpolação, mas apenas a versão básica mais rudimentar com nosso Assim, podemos puxar do pino de execução. Podemos encontrar a velocidade atual definida. Então, definindo o valor que estamos rastreando, é aqui que queremos extrair desse pino aqui, e vamos pesquisar o loop. E desta vez, queremos apenas usar o loop flutuante padrão Então você pode ver que é um pouco mais simplificado. Em vez de ter a corrente no alvo no tempo Delta e uma velocidade de interp, se quisermos alterar a velocidade de interp, precisamos adicionar algum tipo de deslocamento aqui Tudo o que estamos fazendo é fornecer essa curva exponencial, que será nosso Alfa Então, se fizermos o movimento Alpha, podemos colocar isso aqui. Mas, além disso, basicamente ainda estamos fazendo a mesma coisa. Vamos passar de A para B. E eu mencionei isso quando olhamos pela primeira vez para o F nos dois primeiros, temos meio que 0,1 em 0,2 ou ponto A e o ponto B. Então, ainda estamos fazendo a mesma coisa. Vamos de A, que é a velocidade atual, para B, que é nossa velocidade alvo em um período de tempo, e agora estamos baseando isso em nosso próprio Alpha móvel personalizado Então, essa é a principal mudança aqui: a forma como estamos definindo a velocidade atual está sendo atualizada. Então, se continuarmos, podemos realmente excluir isso agora. Então, podemos ver que estamos na maior parte do tempo atualizando nossa base de código. Vou clicar duas vezes aqui novamente para criar outro nó de reenraizamento apenas para manter isso um pouco arrumado, tirar as coisas do caminho nos dar espaço suficiente Então, a última coisa é que queremos definir nossa localização novamente. Também vamos fazer algo um pouco diferente aqui. Então, depois de definir a velocidade atual, uma vez que estamos rastreando a velocidade, queremos extrair nosso pino de execução e pesquisar algo chamado add actor world offset Então, podemos ver a opção logo aqui na parte superior, no Actor world offset Portanto, para nosso caso de uso, essa é, na verdade, a melhor solução em comparação com definir a localização do ator para movimentos conscientes da física. A única coisa que realmente precisamos mudar é clicar com o botão direito do mouse no vetor de localização Delta aqui, dividir o pino da estrutura para que tenhamos os mesmos resultados de antes. Queremos medir nossa velocidade atual, que possamos conectá-la se você quiser, mas neste caso, vou apenas Controlar a velocidade atual de arrasto Vamos multiplicar isso por segundos Delta. Então, obteremos mais segundos Delta do mundo G e conectaremos isso ao nosso resultado aqui. E então, é claro, vamos fazer disso o Y porque estamos nos movendo de um lado para o outro. Então, queremos isso no eixo Y. É basicamente isso. Então, agora atualizamos. Também podemos nos livrar disso. Agora atualizamos nosso código de movimento. Estamos rastreando a velocidade alvo de forma um pouco diferente. Temos nosso alfa de movimento totalmente personalizado baseado em uma curva de decaimento e mudamos um pouco a maneira como lidamos com a velocidade atual e como a conectamos à localização mundial Agora, uma coisa que poderíamos fazer aqui, só para melhorar um pouco as coisas, é voltar a comentar coisas Então, novamente, esse é um bom uso de comentários quando temos essas grandes divisões de lógica específica em nossa , então o que poderíamos fazer é pegar esses nós aqui pressionar C. E se eu quisesse fazer um comentário, talvez eu diria algo como definir velocidade para o avião alcançar E para que eu não precisasse me aprofundar no código mais tarde, eu poderia simplesmente especificar que essa é especificamente a velocidade alvo que estamos analisando. Novamente, eu poderia dar esse tipo de cores mais exclusivas apenas para que os comentários se destaquem de outras coisas como fazer, que criamos anteriormente. Não precisamos fazer isso e deixar tudo muito bonito. Você definitivamente pode se deixar levar por isso. Mas quando mudo a cor das coisas, é mais que, à primeira vista, sei que uso um cinza específico para comentários Eu uso um vermelho específico para códigos potencialmente quebrados ou algo que precisa ser movido todos juntos. Eu normalmente uso, tipo, um verde para fazer. Então, novamente, em um piscar de olhos, eu posso ver como estou lendo meu código Esses são apenas comentários em que preciso me atualizar Isso é algo que eu realmente preciso eliminar mais tarde, e coisas assim podem se tornar úteis Então eu dou a eles uma cor muito azul acinzentada só para me lembrar Basta pressionar Control C e Control V para obter outro comentário aqui, meio que duplicar este, e vamos colocá-lo aproximadamente no lugar para que eu não precise definir a cor novamente. E essa é uma dessas coisas. Depois de se acostumar com atalhos e coisas assim, o pouco de tempo extra necessário para personalizar a cor e o tipo de tema não adiciona muita sobrecarga ao seu tempo de desenvolvimento Então, isso, se eu estivesse deixando um comentário para mais tarde, está nos ajudando a rastrear o Alpha para uso em nossa função de interpolação Mais uma vez, apenas me lembrando de que, especificamente, isso está atualizando a função move Alpha E então queremos talvez mais um comentário. Eu mencionei que não farei isso para todas as linhas de código e não farei isso para o resto do projeto e vídeos, pois os vídeos ficariam muito longos. Mas só para mostrar o conceito, à medida que analisamos alguns desses maiores refatores e mudanças, que podem ser um pouco mais confusos, acho que é definitivamente valioso ver isso Então, vamos apenas colocá-los em seu lugar. E o que eu poderia chamar isso é que estamos atualizando nossa velocidade atual e , em seguida, definindo a localização do nosso avião. E, ao dizer isso, na verdade outra coisa muito útil é que agora estou questionando meu próprio código porque estamos fazendo duas coisas por linha E se você se lembra, eu disse, a regra geral é que, com uma sequência, nós as tratamos um pouco como funções em que as funções deveriam fazer uma coisa específica e outra muito bem. Então, no momento, estamos principalmente seguindo isso. Isso está definindo especificamente a velocidade alvo. Isso é calcular e definir especificamente o movimento Alpha, mas agora isso está fazendo duas coisas Está definindo a velocidade atual e, em seguida, movendo o avião. Então, o que eu poderia ficar tentada a fazer é adicionar outra e depois fixar aqui, controle mamário em X, controle em V. Conecte isso E, mais do que tudo, eu poderia ter deixado isso, mas só para mostrar como é fácil manter seu código limpo e seguir regras e estruturas específicas. Então, agora estamos realmente seguindo as regras que estabelecemos a nós mesmos, e eu só preciso mudar as coisas um pouco e talvez adicionar outro nó de reinicialização aqui. Arrume um pouco as coisas. Novamente, não estamos tentando fazer essa obra de arte, mas quanto mais fácil for trabalhar com ela, nosso eu futuro ficará grato O que estamos fazendo agora é pensar no código. Podemos vir e fazer seu comentário final. Então, isso é definir a velocidade atual com base em uma interpolação simples, ou seja, Então essa é a única coisa que essa linha está fazendo especificamente. E então, novamente, precisamos de um comentário final, então o controle C controle V colocou isso em prática. Quer dizer, eu tenho um tijolo lógico muito bom, então agora isso é simplesmente atualizar a localização do avião. Então, se fôssemos ler isso, podemos ver especificamente o que está acontecendo. Estamos definindo a velocidade alvo. Estamos atualizando o movimento Alpha, que será usado posteriormente para a função de interpretação. Estamos usando essa função de interpretação e definindo a velocidade atual com base nela. E então estamos pegando essas variáveis e atualizando a localização final do avião. Então, isso agora é provavelmente melhor do que o que eu tinha há pouco. É apenas uma pequena mudança, mas, novamente, seguindo essas regras, pensamos como pequenas funções, essencialmente, e todas elas estão fazendo esse trabalho muito específica e o estão fazendo bem Mantenha as coisas arrumadas, mantenha as coisas fáceis de ler. E se precisarmos voltar e remover algo, adicionar algo , será muito mais fácil atualizar e corrigir nosso código no futuro. Então é como uma tangente lateral lá. Eu não esperava me aprofundar muito na limpeza do código, mas vi a oportunidade novamente porque meio que fui contra o que mencionei no início do tópico Feito isso. Esse é o movimento agora pronto para começar. O que precisamos ver a seguir é o sistema de rotação. Vai ser o mesmo problema porque estamos usando o mesmo tipo de coisa. Se formos lidar com a rotação. Temos uma função muito simples, que é, novamente, a coisa muito boa que o Unreal faz por nós Ele fornece muitas dessas funções auxiliares, este R integrado intercala dois, simples e simples, um nó, alguns nós próximos a ele para o cálculo e, em seguida, define a rotação ativa, e estamos prontos para testar Mas algo que as pessoas precisam saber é que, geralmente, isso só serve para testes. Provavelmente queremos começar a criar nosso próprio código quando ficarmos mais sérios e, na verdade, com as coisas. Antes de fixar a rotação, basta verificar algumas coisas no movimento da alça. Como vamos dirigir a velocidade atual um pouco mais manualmente dessa forma, provavelmente queremos ter certeza de que, ao clicar nela anteriormente, percebi velocidade atual tem um valor padrão O valor padrão aqui era essencialmente quando essa era originalmente nossa velocidade geral de movimento. Então, vamos querer redefinir isso e garantir que a velocidade atual, a velocidade alvo, a velocidade de interposição do movimento tenham um valor, mas a velocidade alvo da multidão e a velocidade atual estão todas definidas como zero por padrão, e só serão calculadas em tempo A outra coisa, o mesmo problema, muito fácil de fazer novamente, é que quase esqueci de marcar a função de varredura, então ela tem a mesma função da função de definir localização real que usamos anteriormente, então precisamos ter certeza de que a varredura Isso deve ser muito bom para começar. Isso não funcionará totalmente no momento. E acabei de perceber que fizemos isso da maneira errada. Acho que estava dizendo para você subtrair a coisa certa anteriormente, mas durante a implementação, eu conectei isso da maneira errada Então, se clicarmos com a tecla Alt após o exponencial, é muito importante aqui, queremos subtrair nosso cálculo de Então, estamos trabalhando de volta a partir de um. Estamos criando essa curva de decaimento a partir de uma com base nessa atualização ao longo do tempo Então, sim, está apenas testando rapidamente para garantir que isso ainda funcione. Como mencionei, a rotação vai ser um pouco trabalhada, mas ainda temos o mesmo movimento, então temos um bom movimento suave, a rotação, porque é baseada na velocidade que temos , está completamente quebrada, mas isso é algo com o qual podemos trabalhar, e meio que melhoramos isso à medida que avançamos e refatoramos a rotação Então, apenas algumas recapitulações finais. Certifique-se de que estamos fazendo nosso cálculo para nosso valor exponencial e, em seguida, retirando isso de um. Portanto, é um menos nosso cálculo exponencial aqui, e esse é o resultado que queremos para nosso movimento Velocidade atual, velocidade alvo, ideal é que você seja definido como zero. Estamos calculando isso aqui, multiplicando-os novamente, e obtemos um bom movimento independente da taxa de quadros Então, isso ainda é meio que uma sensação e funcionamento muito parecidos com os que tínhamos anteriormente. Você pode achar que precisa ajustar um pouco a velocidade agora, mas estamos muito perto do que tínhamos As rotações foram interrompidas, o que, como mencionei, é esperado porque estamos usando um cálculo muito simples aqui com base na velocidade alvo e apenas multiplicando isso pelo fator de inclinação, e agora a velocidade alvo ou velocidade atual, desculpe, está sendo tratada de uma maneira Com isso feito, porém, melhoramos o movimento. É uma base muito boa para começar, e então podemos pular direto para a rotação Agradeço esses tópicos bastante pesados à medida que analisamos isso, mas espero que, passando algum tempo entre os tópicos, faça uma pausa novamente sempre que achar necessário e realmente tente entender o que estamos fazendo e por que essas mudanças funcionarão Eu tentei explicar a matemática e outras coisas por trás delas. Algumas coisas são muito difíceis de transmitir sem realmente ter experiência prática com o código-fonte. Outra coisa é que você pode acessar código-fonte do Unreal Engine encontrar a função Ler em C plus plus E, novamente, mesmo que você não entenda totalmente o C plus, tudo bem. A maior parte é muito legível por humanos. Os comentários estão todos lá. Está explicando o que está acontecendo na função F interp passo a passo E, às vezes, basta mergulhar no código-fonte dessa forma, já que tudo está prontamente disponível Seja muito útil e você começará a entender algumas das limitações de usar apenas a funcionalidade reconstruída e predefinida fornecida pelo Unreal Engine Não quer dizer que seja ruim, como mencionei, ele tem seus casos de uso, mas encontramos esses casos marginais em que simplesmente não funciona e precisamos criar nosso próprio código 18. 17 — Rotação melhorada: Movimento configurado. Agora precisamos fazer a mesma coisa para nossa rotação. Ainda queremos estar dentro do avião, player. Vamos entrar na função de rotação da alça. Vou fazer uma atualização muito parecida aqui. Outra coisa boa é que podemos começar a tornar o código um pouco mais uniforme, porque a lógica por trás dele será muito semelhante. Então, na verdade, podemos dar nossos passos iniciais aqui. Vamos reduzir isso. Vamos soltar isso e guardar qualquer coisa que possamos usar um pouco mais tarde, mas, como você disse, anteriormente, vamos nos livrar completamente disso até o final Agora, a primeira coisa é que queremos obter nossa sequência. Podemos fazer a mesma coisa novamente. Então, pegaremos um nó de sequência e começaremos a mantê-lo organizado porque precisaremos fazer muitos cálculos para isso Então, vamos nos certificar de que mantemos nosso código alinhado de forma clara e organizada Agora, precisamos fazer um pouco mais para a rotação porque, como eu disse, anteriormente, era um valor meio arbitrário apenas sendo multiplicado pela velocidade atual sem nada mais contabilizado Então, vamos fazer um pouco de fixação e arrumação para tornar isso um pouco mais refinado também O que queremos é que usemos nossa velocidade atual. Chegaremos à velocidade atual que temos, então ainda vamos baseá-la aproximadamente na mesma coisa, mas com algumas modificações. A maneira como vamos fazer isso é a partir da velocidade atual. Queremos fazer uso de algo chamado intervalo de mapas fixado Isso mapeará uma faixa de valores para outra, perfeita para converter a velocidade em um ângulo de inclinação específico No alcance A, nossa velocidade de movimento será negada. Então, clicaremos com o botão direito do mouse, pesquisaremos a velocidade de movimento porque ela está sendo acessada pela nossa classe principal, a velocidade-alvo real , a velocidade máxima que podemos mover, então obteremos a velocidade de movimento. Vamos multiplicar isso por menos um. Sinta-se à vontade para se dar espaço à medida que avança. Então essa será nossa faixa A. Na faixa B simplesmente estará a velocidade de movimento, então inalterada E, novamente, estou me dando um pouco mais de espaço, pois precisaremos de mais coisas aqui embaixo. Então, precisaremos de um novo valor para nossa inclinação máxima e mínima que queremos alcançar Então é aqui que, na verdade, não temos um pouco de controle. Então, podemos dizer que queremos que ele seja capaz de inclinar no máximo 15 graus a qualquer momento ou 25 ou o que você quiser na categoria de rotação E, novamente, se você tiver categorias, tudo bem. Caso contrário, basta pegar qualquer flutuador que você tenha. Vou pegar meu fator de inclinação, duplicá-lo e chamá-lo de inclinação máxima. Clique em compilar e acho que, por padrão, darei a isso um valor máximo de 15, então isso reduzirá a rotação de 15 graus Você poderia criar uma inclinação mínima, que seria menos 15, mas semelhante ao que fizemos aqui, em vez disso, vamos pegar nossa inclinação máxima e multiplicá-la por E essa será a nossa faixa A, e você começará a ver como tudo isso funciona. Espero que, como você vê, eles se juntem. E eu vou pegar nossa inclinação máxima e então essa será nossa faixa de saída B. Então, vamos pegar nossa velocidade atual, qualquer que seja nossa velocidade atual, conforme calculada, conforme calculada, se estiver em algum lugar entre zero e menos nossa velocidade máxima de movimento Acho que foram 1.000. Então, nossa inclinação máxima variará de zero a menos 15 com base em uma espécie de porcentagem, um valor uniforme que corresponderia aproximadamente à velocidade E vice-versa, se estivermos nos movendo para a direita , levaremos nossa velocidade máxima de movimento, zero a 1.000 positivos, e eu escolherei um valor de inclinação de 0 a 15 graus Então é assim que podemos realmente fixar, em vez de apenas ter uma rotação completamente arbitrária de qualquer Na verdade, estamos baseando isso especificamente entre qualquer que seja nossa velocidade atual e, em seguida, mapeado entre as velocidades reais que podemos Isso facilita muito a atualização. Se quiséssemos dizer que temos mais inclinação, mas mantemos a mesma velocidade , podemos simplesmente aumentá-la Eu poderia dizer que agora você pode inclinar até 25 graus em vez de apenas 15 Para testar, acho que vou mantê-lo em 15, mas podemos contornar isso com muita facilidade. Não queremos promover isso para uma variável. Então, o que quer que isso calcule, vamos promover para outra variável Vou chamar isso de inclinação de alvo. É muito semelhante à forma como a primeira coisa que fizemos em movimento foi calcular nossa velocidade alvo. E conecte isso ao zero, mova isso para cima. E provavelmente teremos que fazer uma boa quantidade de ajustes aqui para manter isso mais legível, só porque há muito mais tipos de matemática acontecendo nessa função A rotação é sempre um pouco mais complexa e complicada do que calcular o movimento ou o tipo geral de localização ou até mesmo mais complexa e complicada do que calcular o movimento ou o tipo geral de localização ou deslocamentos de escala Agora, o alvo Alpha é na verdade tão parecido que vou ficar um pouco preguiçoso Vou voltar ao movimento das alças. Vou pegar todo o código aqui, pressionar o controle C, então vou pegar todos esses nós aqui. A única coisa que não queremos é a mudança Alpha. Vou voltar aqui para a rotação, e vamos conectar isso a um valor em um momento. A única coisa que talvez queiramos fazer é mover nossa inclinação alvo para a categoria de rotação Na verdade, vou renomear isso porque temos algumas convenções de nomenclatura ligeiramente diferentes em Então, vou pegar a velocidade de interposição de rotação e alterá-la para inclinação, porque decidimos que todo o resto está sendo classificado como inclinado em vez de inclinado em vez Vou controlar o arrasto e a velocidade de intercalação da inclinação. E conecte isso aí. Assim, podemos nos livrar da velocidade de interação do movimento no início Mas, além disso, estamos fazendo exatamente a mesma coisa. Estamos calculando nossa velocidade de interposição de inclinação multiplicada pelos segundos do Delta mundial G, multiplicada por menos um, obtendo o retorno exponencial e, em seguida, estamos criando isso novamente, em seguida, estamos criando isso novamente, nossa Então, estamos retirando todos esses valores de um. Então, os resultados disso serão outra nova variável, então vamos promovê-la para outra variável, e vamos chamá-la de Tilt Alpha. Porque vamos querer fazer a mesma coisa novamente. Conectaremos isso ao nosso próprio nó de interpolação ou loop, do qual teremos controle total Então, vamos adiantar isso novamente tentando manter as coisas um pouco arrumadas Acho que só por questões de limpeza e espaço, vou deletar isso agora Não precisamos passar passo a passo, como fizemos anteriormente. Simplesmente não usaremos nada do código antigo aqui. Então, vamos criar outro pino de sequência. Queremos fazer nossa próxima etapa da lógica. Esse é muito simples. Então, muito semelhante novamente ao terceiro estágio em nosso código anterior. Vamos definir nossa inclinação atual. E acho que só de olhar para isso agora, provavelmente vamos começar a misturar valores aqui. Então, até que queiramos e atualmente estamos usando o fator Tilt, acho que vamos perder Então, vou renomear esse fator de inclinação para inclinação atual E essa palavra está lentamente perdendo todo o significado. Eu já disse isso muitas vezes. Vamos arrastar isso para dentro e conectar o pino de execução. E, novamente, o valor que queremos preencher aqui, garantindo que, se clicarmos em compilar, isso não tenha mais um valor padrão, então vamos defini-lo como zero Esse valor será calculado com base em outro loop. Então, a mesma coisa novamente, um loop flutuante. E a mesma coisa novamente. Então, vamos pegar nossa inclinação atual, nossa inclinação alvo e nosso Alpha. Tão bonito e simples. Praticamente, como mencionei, gosto do movimento, mas agora tudo está relacionado à rotação ou inclinação. Então você pode ver o padrão. Na verdade, conseguimos usar basicamente o mesmo código. Então você não entendeu isso uma vez? Muito fácil de reutilizar e refazer. Precisávamos ficar um pouco mais complexos com parte inicial da rotação aqui em cima, mas, por outro lado, era muito semelhante Então, podemos fazer a mesma coisa novamente. Queremos mais um pino, e isso vai realmente usar esses valores e definir a rotação. Então, a mesma coisa novamente. Desta vez, queremos usar a chamada da função set actor rotation. Então, vamos colocar isso aqui, e voltaremos e faremos uma pequena limpeza com alguns reenraizamentos um pouco mais tarde Vamos dividir o pino da estrutura como fizemos anteriormente. Vamos pegar nosso valor de inclinação atual e conectá-lo ao que estamos fazendo isso no rolo E é basicamente isso, mas temos os mesmos passos novamente. Portanto, defina o alvo, defina o Alfa, defina o atual e use o atual como valor. Agora, vou entrar, como mencionei, vamos arrumar um pouco porque está ficando um pouco apertado e difícil Acho que tudo bem se eu não vou gastar muito tempo imprimindo os nós, mas isso é suficiente apenas para manter as coisas separadas E, como mencionei, não quero gastar muito tempo apenas comentando Não é a coisa mais útil de se ver na transmissão ou em um vídeo. Mas se você quiser fazer algo semelhante, apenas uma pequena coisa entre os tópicos, talvez novamente, pause o conteúdo e diga que está fora de uma tarefa para garantir que você entenda o que está acontecendo Leia o código e a rotação e veja se você pode fazer alguns bons comentários para descrever exatamente o que está acontecendo aqui, por que estamos usando o grampo de alcance e coisas assim E o principal é que, se você precisasse voltar e examinar o código em um ou dois meses, de relance, é muito mais fácil ver o que está acontecendo do que isso, atualmente, pois eu precisaria voltar e ler em profundidade Mas vamos verificar se tudo está funcionando. Acho que a principal coisa que temos nossa inclinação máxima está definida como 15, então devemos ver apenas uma inclinação de 15 graus de qualquer E, obviamente, estamos apenas negando isso com base na velocidade do movimento A velocidade de movimento ainda é 1.000, o que eu acho que está perfeitamente correto. Se parecer um pouco mais lento, podemos voltar e aumentar isso Quanto à velocidade de interação, acho que queremos diminuir um pouco a velocidade. Acho que vamos reduzir isso para três em vez dez porque nossa curva de decaimento funcionará um pouco diferente do que estamos fazendo com F interp dois e, em seguida, a corrente alvo e o Alpha devem ser definidos em tempo de execução, então eles devem começar em zero, o que é perfeito E então estamos apenas usando isso aqui. Então, acho que isso deve funcionar agora. Então, se voltarmos, aperte play. Sim, lá vamos nós. Parece que parece diferente, mas podemos ver que é praticamente o mesmo. Acho que meio que prefiro a aparência. É muito mais simples, só que parece um pouco mais refinado. Então, isso é muito bom. E, como mencionei, agora é aqui que entra a flexibilidade. Se você quisesse alterar a velocidade, talvez a intercalação fosse muito lenta. Nós podemos aumentar isso. Então, voltaremos ao modo de jogo aqui. Então, estamos voltando a esclarecer você um pouco mais rápido. Então, tudo bem. E então, se você quiser, como mencionei antes, se não tiver certeza do que algo está fazendo ou para que lado um valor deve seguir, se você o torna realmente drástico, fazer uma mudança realmente grande E você pode ver que é quase como contra-atacar quando nos soltamos Então, a decadência está acontecendo muito mais rápido e estamos contra-atacando Então, isso pode parecer um pouco melhor, na verdade. Então, talvez eu estivesse errado, talvez ir para um valor mais alto em vez menor teria sido melhor para isso, agradável e fácil de testar, mas isso é o principal. Tente incorporar a maneira como você pensa sobre sua própria base de código Facilitar a atualização e o ajuste posterior aumentará a probabilidade de você refinar o jogo e melhorá-lo você refinar o jogo e melhorá-lo Se for realmente difícil trabalhar com seu projeto, é muito menos provável que você queira refiná-lo Passe esse tempo para melhorar o jogo. Então, é mais uma questão de design , na qual é sempre divertido pensar. A última coisa é a inclinação máxima. Então, se pegarmos a inclinação máxima, se eu fizer algo muito maior, como 45 graus só para mostrar a diferença que podemos obter, se flutuarmos, você pode ver que quando começamos a velocidade máxima, estamos atingindo aquele ângulo de inclinação máximo mais alto Então é assim que isso entra em jogo. Provavelmente não quero que ele gire muito, mas talvez você queira aumentar algo mais como 25 para torná-lo mais visível visualmente Mas a principal coisa que temos sobre a implementação anterior é, como você viu. Na verdade, não estava fazendo nenhum cálculo específico para atingir um determinado ângulo de rotação com base na velocidade ou qualquer coisa. Estava indo o mais longe possível dentro de um determinado período de tempo. Já agora, temos um pouco de controle. Dependendo da nossa velocidade atual, podemos controlar exatamente o quanto giramos E então, a coisa mais importante a verificar é que vou usar alguns comandos do console para me livrar dos inimigos. Nós não precisamos deles. Continue voando até nós. Vou entrar no modo de jogo. Vou dar a mim mesmo o comando stat FPS do console, para que possamos ver que estou rodando a 120 Eu me coloquei diretamente em 30. E, novamente, devemos ver que estamos obtendo uma estrutura muito menos agradável de se ver, mas ainda estamos obtendo apenas 25 graus de rotação e estamos atingindo o que esperamos ver em um momento, aproximadamente na mesma Então, se eu agora aumentar isso para 60, estamos alcançando apenas a mesma rotação, o mesmo tipo de inclinação de inclinação ou inclinação de rotação, desculpe Estou fazendo isso aproximadamente na mesma quantidade de tempo. E então, se subirmos para 120 ou, na verdade, vamos simplesmente abrir o limite Eu vou dizer cerca de 600, então eu posso obter cerca de 300 FPS. Parece mais suave, mas os movimentos acontecem na mesma velocidade e a rotação está levando o mesmo número de quadros ou segundos para chegar lá Então, agora corrigimos completamente o problema de independência da taxa de quadros que tínhamos anteriormente. Então, lembre-se de que o movimento não era realmente um grande problema, mas a rotação tinha um problema em que, embora estivéssemos multiplicando por segundos por causa disso, exatamente o tipo de lógica que as funções F inter estão usando, lembre-se de que basicamente conseguimos girar a asa até o chão porque a rotação não estava bloqueada porque a rotação As diferentes taxas de quadros o estavam afetando de forma diferente. Então, agora resolvemos completamente esse problema. Tivemos que nos aprofundar um pouco mais na matemática, usando a função de espreita simplificada, mais rudimentar simplificada Mas, ao aguentar um pouco a chuva com nosso próprio código, agora resolvemos vários problemas que foram lançados. Você provavelmente encontrará muitos jogos porque muitos jogos são lançados com base em exemplos de conteúdo, código de produto e coisas assim Esse é o teste completo. Mesma velocidade de movimento. Temos os mesmos limites de rotação. Não há nenhuma asa atravessando o chão. A fórmula exponencial é o que nos dá a interpretação matematicamente correta em qualquer taxa de quadros Espero que um conteúdo mais aprofundado como esse não tenha congelado completamente seu cérebro e impedido você de acompanhar. Esse foi realmente o objetivo dos tópicos quando eu os criei: tentar fazer com que as pessoas pensem mais sobre sua base de código e o que está acontecendo nos bastidores e não apenas acompanhem. Então, espero agora você possa ver os benefícios do que somos. Eu mencionei desde o início Isso está demorando muito mais do que poderia ter acontecido, e eu poderia ter simplesmente editado muitas informações triviais ou o que pode ter parecido informações triviais, mas acho que você teria perdido muitas que agora você possa ver os benefícios do que somos. Eu mencionei desde o início. Isso está demorando muito mais do que poderia ter acontecido, e eu poderia ter simplesmente editado muitas informações triviais ou o que pode ter parecido informações triviais, mas acho que você teria perdido muitas das potencial de aprendizado e realmente entender o que você está fazendo. O objetivo aqui é que, com sorte, você possa assistir algo assim, evitar assistir a mais duas ou três outras séries de tutoriais ou cursos ou qualquer que seja o caso, porque na verdade você está aprendendo muito mais sobre os sistemas e consertando coisas que até existem no conteúdo oficial de aprendizagem da Epic Então, espero que haja valor nisso. Então, se você realmente quiser começar a refinar seu projeto agora, é aqui que você provavelmente tem o tipo geral de compreensão do que vamos fazer Organizamos nosso projeto em um local bastante rígido e sólido Então, se você quiser começar a experimentar entre os tópicos, é aqui que você pode querer frear um pouco . Novamente, isso não é uma corrida. Não pretendemos concluir o projeto o mais rápido possível Nosso objetivo é fazer com que você saia, entenda o que está fazendo e como expandir o que já aprendeu Então, talvez faça algo simples, mesmo que seja apenas entrar em seu próprio código, ver se agora você pode comentar e descrever o que seu código está fazendo para si mesmo usando alguns bons comentários ou categorizando para si mesmo usando alguns bons comentários as variáveis Se você percebeu que tem essa longa lista de variáveis e pode ver uma maneira de melhorá-la, comece a adicionar categorias às suas variáveis, coisas simples para manter seu projeto estruturado, organizado e fácil de trabalhar Lembre-se de que o objetivo principal é que as sequências sejam seu controle de fluxo, tornando-as mais legíveis, como código de script normal ou código Bons comentários, explique a intenção em vez de apenas descrever a variável Coisas como você poderia simplesmente fazer um comentário dizendo interpolação alfa, mas um bom comentário seria calcular os valores de independência da taxa de quadros com base na interpolação alfa, coisas assim para fornecer um descritor, de uma forma rápida do que você está fazendo e por quê Com isso feito, porém, o sistema de movimentação está pronto para produção. Temos movimentos e rotação suaves e controlados com taxa de quadros independente para o jogador, que é a classe mais pesada e complexa que teremos no projeto seguir, veremos como gerar inimigos dinamicamente durante o jogo, em vez de apenas colocá-los manualmente, o que obviamente será um pouco restritivo para um pouco restritivo para 19. 18 — EnemySpawner: É hora de automatizar a geração de nossos inimigos. Estaremos construindo isso de forma flexível desde o início. começar, isso funcionará para os inimigos, mas vamos prepará-lo um pouco para o futuro, então isso funcionará com coisas como objetos de fundo ou qualquer outra coisa que precise aparecer com o tempo. Chega de colocar inimigos manualmente, o que será o primeiro passo importante. Então, para começar, vamos até nossa pasta Blueprint e vamos criá-la dentro de uma nova estrutura de pastas Então, vou pressionar Control Shift e N para uma nova pasta, chamada de spawners Clique com o botão direito do mouse, iremos para a aula Blueprint e queremos criar nossa classe de ator padrão do blog Como mencionei, isso é apenas um contêiner. Tem uma transformação, um lugar no mundo, e então podemos colocar nossa lógica aqui. Vamos dar a esta o nome de BP Underscore Spawner Então, como mencionei, planeje um pouco para frente. Não vamos especificar que isso será apenas para inimigos, e talvez tenhamos outros geradores que serão filhos dessa classe com herança Dentro disso, queremos apenas ir direto ao nosso gráfico de eventos. Não há nada que precisemos adicionar visualmente para representar isso. Acho que, nesse caso, podemos nos livrar do fato de o ator ser uma sobreposição, e a maioria das coisas aqui deve ser responsiva, então não devemos fazer verificações e atualizações constantes nos eventos, para que possamos nos livrar dessas duas chamadas de função Podemos orientar nossa lógica central a partir de uma função personalizada. Acabei de mudar isso. Vamos criar uma nova função aqui, e eu vou chamá-la de ator de spawn Então, novamente, tudo o que estamos fazendo à medida que avançamos e planejamos é tentar manter isso muito genérico. Não estamos dizendo gerar peça de fundo, captador de geração, geração de inimigo Tudo o que precisamos transmitir é um argumento sobre o tipo de ator que queremos gerar, e provavelmente precisaremos talvez de alguma rotação aleatória, um deslocamento, localização e coisas assim Podemos tornar isso agradável e genérico e tornar tudo muito reutilizável Então, sempre tentando planejar com antecedência. Lembre-se, pense com preguiça, planeje o programa uma vez e use quantas vezes for possível Dentro dessa função, vamos extrair do pino de execução e, na verdade, temos uma função embutida dentro do Unreal, chamada spawn actor from class Quando estamos usando essa função, a principal coisa que queremos, como mencionei, é uma transformação, então onde queremos que isso apareça e especificamente, em que tipo de classe queremos gerar Então, no momento, isso poderia ser algo como nosso inimigo, mas, novamente, isso seria muito específico. Então, se destacarmos e passarmos o mouse sobre o pino roxo aqui, podemos ver que isso se refere especificamente ao tipo de ator Portanto, esses pinos roxos são as referências reais da classe em si, não uma instância no mundo Quando temos esses pinos azuis, essa é uma instância real que existe no mundo Podemos pensar nos pinos roxos como uma referência à localização dentro da nossa estrutura de pastas Então, vamos fazer uso dessa digitação genérica. Vamos partir daqui e, na verdade, promoveremos isso para uma variável. Vamos dar a este o nome do tipo de ator. Use isso agora que podemos preencher isso com qualquer tipo de ator em nosso projeto, seja um inimigo, uma picape, uma peça de fundo quando os adicionamos, o que quisermos, agora podemos fazer com que essa função gere peça de fundo quando os adicionamos, o que quisermos, agora podemos fazer com que essa função gere isso em um determinado ponto As principais coisas que vamos querer expor são os detalhes da transformação de spawn Então, se escrevermos, clique aqui, dividiremos a estrutura pi. Vamos deixar a escala de transformação de spawn para 11 e um Geralmente, tentamos não substituí-los. Se tudo foi configurado corretamente, como neste projeto, todos os ativos devem estar na escala correta para começar. Então, vamos manter isso e assumir que os ativos são importados e funcionam conforme o esperado. Você tem a opção de randomizar ou deslocar a rotação, mas vou manter isso limpo por enquanto, e sempre podemos voltar e refazer Em vez disso, vou clicar com o botão direito do mouse e pesquisar por Obter rotação de atores. A razão para isso é que isso significa que podemos conectá-lo diretamente. E onde quer que giremos nosso gerador, temos controle total no editor, então agora essa é mais uma ferramenta de edição, onde se eu quiser que isso gere coisas para os lados, só preciso me lembrar de girar o gerador real para girar alternativa seria expor isso a uma variável e conectar manualmente a rotação, mas acho que essa pode ser uma ótima maneira de trabalhar É um pouco mais intuitivo para mim, desde que não seja muito restritivo, o que acho que, neste caso, devemos ficar bem Para a localização, vamos retirar daqui e adicionar um pino positivo. Este pode precisar de um pouco de randomização, alguma variação e compensação fornecida Se clicarmos com o botão direito do mouse, podemos pesquisar a localização do ator G. Então, a mesma coisa novamente, vamos usar as propriedades gerais de onde quer que o gerador esteja, então esse será nosso ponto de partida básico Agora, para esse tipo de jogo , como sabemos que estamos indo apenas de uma perspectiva de cima para baixo, não precisamos de nenhuma randomização no Z e provavelmente queremos fazer toda a nossa geração fora da tela, que significa que também não precisaremos nenhuma randomização no Então, o que poderíamos fazer é clicar com o botão direito mouse nesse segundo pino vetorial e dividir a estrutura. Vamos usar nosso pino Y aqui e queremos usar esse nó de seleção que vimos anteriormente. Não queremos selecionar float. Queremos este aqui com o ícone exclusivo. Isso nos dá o curinga que usamos anteriormente. Vamos mudar isso para um booleano, então vamos randomizar ou não, e eu vou promover o índice aqui para uma nova variável, e vamos chamá-la de adicionar deslocamento aleatório Novamente, lembrando de dar a isso um B. Se decidirmos adicionar um deslocamento aleatório, queremos fornecer algum tipo valor flutuante dentro de E, novamente, vimos como fazer isso, então agora estamos apenas analisando as funcionalidades e abordagens que já adotamos no passado Então, se isso for verdade, se estivermos adicionando um deslocamento aleatório, extrairemos daqui e usaremos aquela função aleatória flutuante no intervalo que vimos antes E a partir disso, queremos apenas uma distância lateral, ou seja, uma distância lateral mínima e máxima que possamos aplicar Então, se obtivermos nossa flutuação máxima aqui, vamos apenas promovê-la a uma variável, e daremos a essa o nome de distância de deslocamento O mínimo é que, como vimos antes, com velocidades e coisas assim, será o inverso negativo, então podemos controlar o arrasto na distância de deslocamento, multiplicar isso por menos um e inserir o resultado Então, se definirmos uma distância de, digamos, 100 unidades, e quisermos que isso aconteça em qualquer lado do centro da tela, colocaríamos esse ator de desova no centro da tela inseriríamos o valor 100 na distância de deslocamento Isso significa que ele pode gerar -100, 100 positivos ou algum valor intermediário Se decidirmos não expor a variável e não tivermos o deslocamento aleatório ativado , vamos apenas adicionar false Então, vamos adicionar zero à nossa transformação geral, que significa que o ator aparecerá exatamente onde o colocamos É relativamente simples, mas ainda é uma espécie de ferramenta para desenvolvedores, algo que podemos usar se for necessária mais complexidade, mas que nos dá alguma flexibilidade e variação em nosso projeto, geralmente faz com que as coisas pareçam mais interessantes e divertidas de jogar. Algo que eu ainda não mostrei, e quero apresentar aqui porque estamos criando um desenvolvedor muito rudimentar Isso é algo muito útil dentro do Unreal Outros mecanismos fazem coisas semelhantes, permitindo que as pessoas vejam as variáveis fora da classe. No momento, por exemplo, se pegarmos uma de nossas classes geradoras e a colocarmos no mundo, certificando-nos de que compilamos e salvamos tudo, podemos ver aqui que os objetos selecionados, nenhuma das variáveis que acabamos de criar, está realmente Não seria possível entrar manualmente por instância. Então, se tivéssemos três ou quatro desses, não poderíamos escolher que este tinha alguma randomização e uma distância única, e este não tinha randomização, por exemplo Atualmente, temos apenas um lugar em que podemos mudar isso, e isso está aqui no gráfico. Então, ele pegaria esse booleano e o desativaria, e então isso seria ativado ou desativado para todos eles. E da mesma forma, pela distância. A maneira mais útil de substituirmos isso são esses ícones aqui Você pode não ter tocado neles ainda, mas se clicarmos neles, ele fornecerá um pequeno ícone de olho. Por padrão, eles começam fechados e podemos abrir o olho. Em outros idiomas, isso é chamado de tornar algo público. Ele é exposto a outras classes e pode ser lido e gravado fora dessa partir de um modelo irreal, isso é apenas tornar a variável editável essencialmente fora da classe Então, se entrarmos em nosso ponto de vista novamente com os mesmos objetos selecionados, você pode ver que, no menu suspenso padrão, temos acesso ao tipo de ator que queremos que isso Então é aqui que podemos começar a fazer coisas como essa: criar inimigos. Não vamos fazer isso, mas isso pode gerar jogadores. Portanto, já temos alguma flexibilidade no que eles vão gerar E então, como os inimigos podem querer ser mais aleatórios, podemos ativar essa opção como verdadeira para adicionar um deslocamento aleatório em qualquer direção, e podemos definir que seja, como eu disse, talvez 100 unidades à esquerda e à direita do gerador. Muito bom e simples, como você viu, não é uma configuração muito complexa, mas já temos uma quantidade relativa de flexibilidade e liberdade na forma como a usamos. Então, no momento, se adicionássemos isso ao início do jogo e fizéssemos com que fosse chamado uma vez, um inimigo não seria um grande desafio para nosso jogador. Então, o que queremos fazer é adicionar alguma desova contínua. Vamos evitar usar coisas como atrasos e loops, pois isso se torna confuso e Então, você já deve ter visto algo assim antes, onde, ao começar a jogar, novamente, eu só quero visualizar algumas das coisas que vi em muitos projetos Então você pode ter algo como entraremos pela primeira vez e geraremos um ator uma vez. Em seguida, adicionaremos um atraso. Portanto, um atraso é apenas um tipo de processo de espera cronometrado. Vamos esperar, digamos, 3 segundos. Antes de fazermos a próxima coisa, e depois geraremos o ator novamente. E você pode ficar tentado a vir aqui e, talvez, depois de cada vez que isso for feito, tente encontrar uma maneira de se lembrar de si mesmo Vai ficar confuso. Você acaba vendo pessoas fazendo coisas assim, vamos repetir o plano de fundo, e você acaba com esse loop infinito em que as pessoas dizem que depois de gerarmos isso, vamos esperar mais 3 segundos e chamar o ator de spawn Então, vamos evitar esse código de estilo iniciante. O que queremos usar em vez disso é algo chamado temporizadores. Eles são muito mais limpos e nos dão muito mais controle sobre se e quando eles são chamados. Então, a partir de nossa jogada inicial, o pino de execução, queremos encontrar uma função chamada I valid. Queremos essa opção com o ponto de interrogação na parte inferior. Isso é verificar se outro objeto ou ator é válido atualmente, ou seja, ele existe e não está sendo enviado para a coleta de lixo para limpeza se estiver sendo destruído ou algo parecido Do objeto de entrada, então o que queremos verificar se ele existe, vamos extrair daqui e usar essa função embutida, o peão get player Então, isso é, novamente, apenas uma dessas coisas a considerar. Isso acontece em muitos jogos para novos desenvolvedores em que você criou um jogo como esse e os inimigos destruíram o jogador. Mas mesmo quando você está na tela de fim de jogo ou está apenas esperando pelos créditos ou o que quer que esteja acontecendo depois, você pode ver o inimigo ainda aparecendo ou atirando no jogador, espécie de cachorro empilhado em um cadáver Parece um pouco intenso, e geralmente é porque não há nenhuma verificação no meio do jogo para ver se os jogadores realmente estão ver se os jogadores realmente classificados como mortos ou não estão mais disponíveis O que vamos fazer é que, se o jogador for removido do jogo, não haverá mais necessidade de os inimigos aparecerem, então vamos parar Se isso for verdade, então se o player ainda for válido, vamos chamar uma função aqui, que é o cronômetro definido pelo nome da função Queremos essa opção aqui, e a primeira coisa que podemos preencher é a hora aqui. Então, esse é o tempo que vamos esperar até essa função que criaremos em um momento seja chamada. Então, por enquanto, podemos partir daqui e procurar outro flutuador aleatório no alcance E um pequeno truque, que pode ser muito útil quando você não quer apenas ter o mínimo e o máximo ou algo que seja o inverso um do outro Podemos fazer uso de algo chamado vetor dois D. Então, se criarmos uma nova variável, chamaremos essa variável de intervalos de geração E vamos descer isso, e vamos pesquisar aqui, em vez de um vetor, que é um valor flutuante de três pontos, também vamos procurar um vetor. Queremos este aqui embaixo, o vetor dois D. E se clicarmos em Compilar, podemos ver que tudo isso são apenas dois valores de ponto flutuante, onde o valor X será nosso mínimo e o valor Y será o máximo Então, podemos definir isso para algo como um mínimo de 3 segundos antes que algo apareça e um máximo de seis E podemos voltar e ajustar isso mais tarde. Podemos arrastar isso para o gráfico, clicar com o botão direito do mouse no pino da estrutura, dividir o pino da estrutura aqui e podemos dizer mínimo, máximo. Portanto, uma boa maneira limpa e organizada de configurar a função de temporização Para o nome da função, temos nosso ator de spawn aqui. Uma coisa que eu sempre costumo fazer, novamente, em parte porque sou preguiçosa e não quero digitar coisas, mas também para evitar cometer erros de ortografia ou digitação Vou pressionar F dois para renomear isso, pressionar Control N C para copiar e, em seguida, controlar NV aqui para colar isso NV aqui para colar isso, garantindo que tenhamos a mesma grafia, a mesma capitalização, evitando erros no nome porque isso diferencia maiúsculas de minúsculas e precisa ser escrito Não vamos definir isso como loop, mas se você tivesse uma função em que quisesse que ela continuasse constantemente, você poderia configurá-la como loop, e ela continuaria girando e girando e, basicamente, chamando-a chamando-a Querer um pouco mais de controle manual. Vou me certificar de que isso não esteja marcado. E o que podemos fazer é pegar todo esse código, incluindo o que é válido, porque se você pensar sobre isso, quando começamos a jogar, não há razão para que o peão do jogador não seja realmente um objeto válido Sempre existirá quando pressionarmos play. Então, o que vamos fazer em vez disso é clicar com o botão direito do mouse em qualquer um desses nós e reduzir isso em uma função. Vamos dar a isso o nome de call spawn Aca timer. Então, estamos meio que ofuscando um pouco a lógica Então, novamente, as etapas são um pouco mais claras e fáceis de entender à medida que analisamos nosso código. E a maneira como realmente queremos lidar com isso é que provavelmente vamos querer criar alguns inimigos imediatamente Então, em vez de desovar com base em um cronômetro, podemos ignorar Então, começaremos criando um ator diretamente. Vamos colocar isso em nosso pino de execução. E, novamente, pensando na ordem da lógica em nosso código. Assim, sempre podemos refazer coisas como. Vamos começar a jogar e vamos criar um ator imediatamente O que isso vai fazer, vai cair aqui. Em seguida, escolheremos nosso tipo de ator se tivermos um conjunto, escolheremos um local e um deslocamento, se houver um deslocamento a ser aplicado, e selecionaremos a rotação e geraremos isso em um ponto E depois disso, é aqui que podemos começar a fazer um loop quase automático Então, se quiséssemos que isso continuasse, poderíamos pegar nosso cronômetro principal de spawn actor colocá-lo aqui E o que isso fará agora é entrar, e isso é mais importante aqui porque, em tempo de execução, é aqui que, após a primeira ou a segunda aparição, podemos ter destruído o jogador Então, este que eu faço é um cheque válido, um cheque muito simples e barato para garantir que o jogador ainda esteja no jogo. E se estiverem, vamos permitir que ele gere outro ator, usando a função spawn actor, basicamente, chamando essa função novamente após um determinado período ou intervalo de tempo Agora, é algo que eu gosto muito de fazer, e isso é totalmente opcional. Mas como quando usamos a função set time by function name, não podemos clicar duas vezes e descobrir o que ela está realmente chamando, precisamos examinar nossa lista de funções e encontrar o nome correspondente. O que eu gosto muito de fazer é colocar a função aqui e colocá-la abaixo do cronômetro definido pelo nome da função Então, isso significa que se eu estiver examinando meu código no futuro, se eu chegar a esse ponto e perceber que devo corrigir ou alterar algo nessa função aqui, posso simplesmente clicar duas vezes nesse nó e isso me levará ao que essa função está chamando Então, só uma pequena dica, mas acho que pode ser muito útil, especialmente quando você volta para ajustar as coisas. Se isso não for flexível o suficiente, precisávamos remover alguma coisa, apenas uma boa maneira de navegar Mas isso é praticamente tudo o que precisávamos. Esse é um bom tipo de gerador autoencapsulado e autocontrolado, com alguma flexibilidade nos diferentes tipos de atores em que podemos gerar, onde eles vão aparecer e se alguma flexibilidade nos diferentes tipos de atores em que podemos gerar, onde eles vão aparecer e se há alguma randomização aplicada. Também poderíamos descer e expor os intervalos de desova Assim, poderíamos ter cada ator diferente, cada criador diferente, com intervalos de tempo diferentes sobre quando as coisas deveriam gerá-lo intervalos de tempo diferentes sobre quando as coisas Portanto, certifique-se de compilar e salvar. Uma coisa que eu quero acrescentar antes de realmente testarmos isso é que, se formos para a seção de componentes, adicionaremos algo aqui, vou pesquisar o componente de seta. Então, na verdade, há um componente aqui que podemos usar que é apenas uma seta visual. Podemos mudar a cor se você quiser mudar a cor por diferentes motivos. Mas o principal é que, novamente, de relance, isso só nos permitirá saber qual caminho seguir, então o padrão é sempre apontar para frente então o padrão é sempre apontar para Então, se clicarmos em compilar e salvar, voltarmos ao nível principal, podemos ver que, de fato, aqui, os inimigos estarão voltados para o lado errado Então, vou me livrar de alguns deles , vamos testar um de cada vez. Certifique-se de que isso não se sobreponha ao chão, caso contrário, os inimigos não conseguirão se mover E então podemos girar isso 180 graus no Z. E você pode ver que agora está apontando para o início do nosso jogador, o que significa que, se definirmos isso para a classe inimiga, poderíamos atribuir a ela uma distância aleatória de cada lado, e um intervalo de desova ocorrerá Podemos pressionar play, e isso gerará um imediatamente Então, dentro de três a 6 segundos , veremos outro aparecer e pronto Portanto, temos nosso ator de desova aleatório funcionando corretamente. Ao fornecer a rotação que mencionei, podemos ver exatamente onde isso vai aparecer e em qual direção você estará voltado O principal problema que temos agora é, obviamente, que podemos vê-los aparecendo, então queremos recuar um pouco para que eles apareçam fora da tela Eles farão essa animação e, em seguida, aparecerão com esse determinado intervalo Se você quiser colocar uma posição ligeiramente diferente, ou se quiser mais delas, você poderia escaloná-la dessa forma, para que pudéssemos ter vários geradores Você pode fornecer distâncias de deslocamento diferentes, intervalos de desova diferentes e pode escaloná-los um pouco dessa forma Novamente, para tornar a jogabilidade e a interação muito mais interessantes. Acho que, no momento, provavelmente poderíamos escapar impunes com apenas um gerador para nossos inimigos Então, se descobrirmos ou decidirmos que não há o suficiente sendo gerado em tempo de execução, podemos voltar e adicionar mais ou brincar com esses intervalos de geração Então, outro pouco de experimentação ou lição de casa que você pode fazer Você pode fazer algumas coisas simples aqui, como duplicar o spawner e experimentar configurações diferentes, como acabei Experimente diferentes intervalos de desova, diferentes distâncias de deslocamento, ative ou desative E, idealmente, se você saiu do conteúdo até agora e criou seus próprios tipos diferentes de inimigos, você pode ter inimigos que só se movem para frente, para trás ou de um lado para o outro, seja qual for o caso Talvez tente adicionar alguns geradores diferentes para inimigos diferentes só para ver como você pode usar facilmente esse sistema um tanto flexível E isso é o principal aqui. Estamos analisando e pensando em como projetamos nosso sistema. Poderia ter criado uma classe de ator especificamente para gerar apenas inimigos Poderíamos ter entrado na classe e codificado a lógica aqui para gerar inimigos especificamente Então, precisaríamos ter feito a mesma coisa com um tipo de inimigo ou com um plano de fundo diferente quando chegássemos lá Essencialmente, muitas duplicatas funcionam novamente, mais coisas para dar errado e mais bugs para corrigir Já com essa abordagem, podemos reutilizá-la posteriormente para os planos de fundo, diferentes tipos de inimigos, chefes, qualquer coisa para a qual você queira usá-la 20. 19 — ProjectileBase: Entrando em uma das partes divertidas agora, é hora de adicionar um pouco de poder de fogo. Novamente, essa será uma classe de projéteis que funcionará para os jogadores e inimigos Como antes, vamos pensar no futuro, tornando isso personalizável de acordo com as cores e os danos, focando nesse design inteligente desde o início, economizando na duplicação posterior Então, podemos deixar o sublinhado da BP Sponerbse se você ainda estiver aqui Vamos entrar em nossa pasta de plantas. Vou voltar para a pasta principal do blueprints aqui Vamos criar uma nova pasta, então controle a mudança em N, e vamos chamá-la de projéteis Agora, no momento, há uma boa chance de que esse projeto acabe com apenas um tipo de projétil Como mencionei, vamos tentar tornar isso o mais flexível possível. Mas, novamente, em versões mais avançadas ou com luz intermitente deste projeto, você pode querer coisas como mísseis domésticos, lasers, estilo espingarda, projéteis Portanto, talvez nem sempre consigamos reutilizar o projétil que temos Então, ainda vamos supor que talvez queiramos desenvolver isso mais tarde, mesmo que não o façamos para esse projeto menor. Então, vamos clicar com o botão direito aqui novamente dentro da nova pasta. Criaremos uma nova classe de blueprint. Mais uma vez, esse será um ator simples, e daremos a ele o nome de projétil BP Underscore Vamos colocar a palavra base no final mais uma vez, caso queiramos expandi-la um pouco mais tarde com versões infantis semelhantes, mas um pouco exclusivas. Dentro da nossa nova classe de atores, queremos apenas, antes de tudo, criar uma nova malha estática. Então, vamos adicionar um novo componente, malha estática, e podemos arrastá-lo diretamente para a raiz da cena padrão. Então, novamente, fazendo disso o novo componente raiz. Com a malha estática selecionada, vamos para o lado direito. Eu forneci aqui o projétil SM underscore, então vamos selecionar este E esse será nosso visual do projétil. No lado esquerdo, voltamos aos componentes. Podemos soltar essa linha novamente, e podemos ver aqui se pesquisarmos a palavra movimento do projétil Temos nosso componente de movimento de projéteis. Unreal tem um sistema integrado para simplificar parte da configuração Agora, não vamos realmente usar isso porque, novamente, é bom ter controle total de nossa própria lógica. Deixe-me mostrar como isso funciona. Então, se clicarmos em compilar e salvar com esse conjunto ativado, queremos ir para o lado direito aqui no painel Detalhes com o movimento do projétil selecionado Queremos transformar a escala de gravidade em zero. Caso contrário, teremos alguma queda com o tempo. E daremos a isso a velocidade de movimento inicial de 300. Se entrarmos, clicarmos em compilar, entraremos em nosso visor e colocaremos isso no nível Agora, eu não vou apertar play porque queremos realmente ver isso se movendo. Mas a maneira como isso funciona basicamente é que podemos clicar em simular, e veremos que isso dispara em aproximadamente 300 unidades Então, funciona. É agradável e simples de configurar. Mas, como mencionei, há uma razão pela qual não usaremos isso. E isso ocorre principalmente porque o componente inclui replicação de rede, coisas que realmente não precisamos Muitos cálculos físicos, novamente, não são necessários para o que vamos fazer, manejo da gravidade, que desativamos explicitamente, mas ainda está lá Também é um pouco inflexível. Queríamos adicionar coisas como aceleração, ao longo do tempo, localização, tudo isso está meio que bloqueado na implementação do Epix Por muito tempo, acho que o homing não funcionou Existem algumas soluções alternativas que você pode forçar, e a aceleração definitivamente não funciona. É muito difícil enfatizar a velocidade e fazer com que algo pareça um pouco caricatural, passar de 100 unidades de velocidade e depois subir para 600 com o tempo e depois descer novamente É muito difícil controlar a velocidade desses componentes em tempo de execução. Essencialmente, se você gerar isso ao mover 100 unidades, essa será a aceleração, o valor da velocidade desse projétil até você reiniciá-lo ou destruí-lo Então, por esse motivo, vamos nos livrar desse ator e somente por esse motivo. Em vez disso, mostre como podemos implementar uma lógica muito semelhante e muito mais simplista para nosso próprio movimento de projéteis Então, só para que você saiba que estou ciente de que isso existe, vamos excluí-lo. Vamos nos livrar desse componente e, basicamente, lançaremos nossa própria versão personalizada especificamente para fazer o que precisamos em nosso projeto. Então, se pularmos para o gráfico de eventos, vamos fazer o padrão aqui. Vamos nos livrar de nossa Lei para começar a se sobrepor. E lembre-se do que eu disse antes, podemos usar venti, e esse é um daqueles casos novamente, queremos que isso se mova suavemente ao longo tempo com uma lógica de movimento simples Então, é no eventk que queremos que isso ocorra. Fiquei interessado e queria dar uma olhada no código-fonte do Unreal Engine, que é até mesmo assim que o componente de movimento de projéteis está funcionando Isso está sendo executado no Venti para manter as coisas atualizadas constantemente, estrutura independente, agradável e suave A lógica que precisamos para isso é muito simples. Portanto, se retirarmos do nosso pino de execução, procuraremos o deslocamento local do ator de adição Isso garante que a localização do projétil avance em relação à sua própria rotação Então, outra coisa muito boa é que só precisamos nos conectar para a frente quando começarmos a gerá-la. E ao usar essa funcionalidade, ele garante que ele sempre estará se movendo na direção correta. Vamos dividir a estrutura aqui, simplesmente porque sabemos que só queremos que ela se mova no eixo X, para frente e para trás Mas você definitivamente poderia voltar e fazer algum movimento lateral se quisesse transformá-lo em algum movimento lateral se quisesse transformá-lo um projétil teleguiado ou algo parecido Tudo do Delta X. Vamos transformar isso em uma variável para obter um flutuador, e chamaremos isso de velocidade de movimento Clique em compilar e daremos a isso um valor padrão de algo como 2.000 unidades, ou talvez 2.500 Podemos voltar e mudar isso mais tarde se for muito rápido. Então, é claro, só precisamos entrar aqui. Vamos medir nossa velocidade de movimento. Multiplicaremos isso por nossos segundos Delta, fazendo com que, como no movimento do avião, tudo seja independente da taxa de quadros, e então inseriremos esse resultado aqui. E é mais ou menos isso. Temos um movimento de projétil independente da taxa de quadros, que se moverá na direção em que é gerado, tornando-o agradável e fácil de usar tanto para o jogador quanto para o inimigo, independentemente da forma como o avião inicial esteja enfrentando uma implementação simples e rápida, mas é personalizável se precisarmos estender isso personalizável se precisarmos estender Então, nos tópicos anteriores sobre Observando inimigos, mencionei que o projétil estaria lidando com seu próprio sistema de colisão e dano, e é exatamente isso que implementaremos Então, com a malha estática selecionada, vamos entrar nas predefinições de colisão E queremos alterar a predefinição aqui de bloquear tudo para sobreposição ou dinâmica. Então, vamos detalhar isso. Encontraremos a sobreposição ou dinâmica e veremos o que isso faz com as predefinições de colisão O principal motivo é que o projétil não deve empurrar fisicamente as coisas Isso pode acabar em situações em que as coisas parecem problemáticas, em tudo o que realmente precisamos fazer é estar cientes de que elas tocaram E se você começar a ser empurrado para trás ou os inimigos começarem a ser movidos com projéteis, isso pode parecer um pouco estranho para o jogador Se quisermos adicionar o knock back como um recurso, tudo bem, mas faremos isso por meio de código para que tenhamos controle total Geralmente, quando duas coisas se sobrepõem fisicamente à função de bloqueio, não parece uma retração Parece que duas coisas estão lutando para habitar o mesmo espaço, e simplesmente não é agradável olhar para Tudo o que precisamos que o projétil faça é detectar e atingir algo e, quando isso acontecer, causar dano Sem simulação de física ou coisas assim. Faremos a mesma coisa que fizemos antes. Vamos rolar para baixo até o final. Encontraremos a seção de eventos e queremos adicionar o componente on para iniciar a chamada da função de sobreposição aqui Então, quando isso se sobrepõe a outra coisa , como fizemos antes, precisamos descobrir algumas informações e ver se o dano será aplicado Vamos pegar o ator aqui, então o outro ator, novamente, mesma forma que antes, vamos promover isso para uma variável, e vamos chamar essa sobreposição de ator E isso porque é o mesmo motivo que acontece com os inimigos. Vamos querer comparar algumas informações com base nisso. Não queremos continuar puxando esse pino aqui, então usaremos uma variável que armazenamos como referência Então, a primeira coisa que acho que queremos considerar é se a coisa que sobrepomos é referenciada como a coisa que é esponda , ou seja, o Então, por exemplo, se o inimigo disparar, e isso for classificado como um projétil inimigo, não queremos que ele cause dano ao avião do inimigo Da mesma forma, se o jogador disparar um projétil, isso é classificado como projétil de camadas Obviamente, não queremos causar danos a nós mesmos. Então, a primeira coisa que podemos fazer é obter nosso ator sobreposto e verificaremos se isso é igual a um tipo específico de ator Então, se isso for igual a, e pudermos pesquisar outra variável rastreada incorporada fornecida e rastreada pelo mecanismo Unreal por padrão, então também podemos usá-la Vamos procurar o dono do G. Então, sempre que algo é gerado no mundo, é imediatamente dado o conceito do que o possui, que o gerou. Então, podemos usar isso. Portanto, podemos dizer que, se a coisa que sobrepomos também for o proprietário, vamos simplesmente pular a aplicação A principal razão para isso é que talvez queiramos escolher nosso ponto de desova, talvez diretamente no meio do avião Então, haverá um breve momento o projétil que o jogador gera ficará, na verdade, dentro do avião por apenas um Se for esse o caso, vamos simplesmente ignorar a primeira sobreposição aqui, não faremos nada Então, vamos puxar uma ramificação aqui, que é nosso fluxo condicional, então vamos verificar se devemos fazer algo com base nesse resultado E se isso for verdade, podemos basicamente pular, não faremos absolutamente nada Agora, a maneira como geralmente gosto de lê-los, porém, é que gosto de fazer coisas fora da tropa sempre que possível Essa é uma preferência pessoal. Novamente, programadores diferentes sempre terão preferências diferentes sobre como abordam as coisas Mas eu prefiro que meu código finalizado real, o que faz a funcionalidade principal, se torne realidade Então, o que vou fazer é, na verdade fazer um checkout um pouco diferente Eu só queria mostrar de uma forma mais legível antes de tudo, mas com uma pequena alteração, podemos realmente pesquisar que não é igual a. Portanto, um ponto de exclamação igual nos dará uma verificação diferente do fator de sobreposição Vamos conectar isso aqui, e agora isso faz a verificação invertida Então, isso é verificar se a coisa é o dono, e agora é verificar se a coisa não é então. Então, se conectarmos isso em vez disso, obteremos esse resultado aqui. Então, estamos dizendo que se o fator de sobreposição não é o proprietário, e é assim que eu gosto de executar meu código, é que, se esse não for o objeto proprietário, podemos fazer nossa Então, mais uma vez, parte disso é apenas para mostrar a maneira diferente de pensar sobre seu código e a maneira diferente de ter várias abordagens para resolver o mesmo problema, mesmo que várias abordagens para resolver o mesmo problema, se trate apenas de como o código é lido. E isso é bom e simples agora. Podemos pegar nosso ator de sobreposição novamente, arrastá-lo com controle, puxá-lo desse pino, e já fizemos isso antes Vamos chamar a aplicação de dano a essa função universal global. Aquele que pode ser aplicado a qualquer tipo de ator. Então, podemos colocar isso no verdadeiro pino. Se a coisa que atingimos não for nosso dono, podemos causar danos a ela. Acho que, por padrão, darei a isso um valor padrão de 20, então vamos inserir 20 aqui. Vamos promover isso para uma variável. Novamente, lembre-se de que, se você colocar um valor aqui antes de promovê-lo a uma variável, essa variável já o terá armazenado. E o principal é que não queremos números mágicos. Vou renomear este para causar dano de projétil. Clique em compilar e verifique se devemos ter o número 20 preenchido aqui Agora, idealmente, depois de fazer isso, talvez queiramos começar a reproduzir alguns efeitos sonoros e efeitos de partículas específicos do projétil Eu forneci um tipo muito pequeno de faísca em vez de uma explosão total, apenas para indicar que algo atingiu uma superfície em vez de realmente causar uma explosão Então, para fazer isso, vou usar o mesmo conceito que mencionei anteriormente. Vou pressionar C dentro do gráfico de eventos sem nada selecionado. Vou pressionar C para criar um novo comentário, e vou dar um grande sinal de que fazer aqui, e então diremos algo como implementar efeitos. Isso será algo que faremos em nosso passe polonês um pouco mais tarde. Isso é bom. Não, isso só vai nos lembrar de voltar aqui. Como mencionei, normalmente atribuo a isso uma espécie de cor verde amarela apenas para me lembrar e realmente posicionar contra outras coisas que possam aparecer no gráfico Mas o que definitivamente queremos fazer é que, depois de tocarmos nossos efeitos, queremos ter certeza de que o projétil seja removido do jogo Então, vamos sair do pino de execução, procuraremos o ator destruidor e nos livraremos de nós mesmos. O projétil fez seu trabalho para poder ir embora. E é mais ou menos isso. Então, vamos verificar o que sobrepomos. Se não for o proprietário, vamos causar danos. Agora, essa é uma ligação muito segura. Você pode estar se perguntando e se eu bater nos limites laterais ou algo parecido com um piso onde eu possa colocar ou uma picape ou algo parecido Agora, se isso acontecer e eles não tiverem a função de ativação de nenhum dano que vimos anteriormente, podemos ver aqui o evento de qualquer dano. Eles não têm isso implementado dentro de sua base de código, então está tudo bem. Eles receberão essas informações, mas não têm um sistema de saúde nem nada com que lidar. Então, é como uma mensagem descartável muito, muito barata Não teremos problemas de desempenho a menos que façamos algo muito ruim com isso, e isso não fará nada Eu não vou destruir o chão ou as paredes ou qualquer coisa assim Portanto, é uma boa função segura. Não precisamos saber nada sobre o outro ator. Desde que toquemos em algo, podemos descobrir algumas informações genéricas sobre isso. E se acharmos que talvez queiramos tentar aplicar danos, tudo bem. Podemos simplesmente enviar esta mensagem. Então, a última coisa é tornar isso reutilizável. Esse é o dano implementado de uma forma bastante universal. Queremos garantir que nossos projéteis correspondam à cor do atirador, para que o jogador dispare projéteis azuis e os inimigos disparem projéteis verdes ou o que você quiser personalizar Então, vamos voltar à nossa função de começar a jogar aqui. Só queremos fazer isso uma vez quando o projétil for gerado Queremos realmente pegar nosso componente. Podemos fazer alguns códigos nos componentes que já temos, então vamos arrastar isso para o gráfico de eventos e vamos extrair daqui e pesquisar a instância de criação de material dinâmico. Então, só temos essa opção aqui. E esse é um dos benefícios de usar instâncias de material em vez de nosso material mestre O código básico do sombreador está com a instância do material, podemos transformá-las em uma versão dinâmica e, na verdade, podemos atualizar suas propriedades em tempo de execução Queremos pegar o valor de retorno aqui, então essa versão dinâmica que é criada, queremos promover isso para uma variável, e vamos chamá-lo de material R. Então é apenas uma referência ao nosso material. A partir disso, podemos fazer nosso código para alterar algumas das propriedades principais. A principal coisa, se você quiser fazer mais sobre isso, é só saber os nomes das variáveis com as quais você pode trabalhar. E isso é muito simples. Se pegarmos a malha estática, mostraremos rapidamente algumas das outras coisas que você pode fazer depois de aprender uma que estou prestes a analisar com você. Se clicarmos duas vezes no projétil MI underscore, sabemos que esta é nossa instância material Isso abrirá o ativo para nós. E, basicamente, qualquer coisa que eu tenha exposto para você aqui, lembre-se, eu disse que criei esse material grande e um tanto personalizável Qualquer coisa nomeada em nossa seção aqui pode ser acessada em código. Assim, você pode alterar a especularidade em tempo de execução, se quiser fazer com que as coisas pareçam mais brilhantes e potencialmente Você pode alterar a textura em tempo de execução, as cores, as cores de substituição e a propriedade emissiva, se quiser fazê-la brilhar. Você queria fazer. Contanto que você saiba o nome e a grafia específica, você pode alterar e afetar qualquer um deles Então, a maneira de fazermos algo realmente simples para mostrar esse tipo de inação é obtermos nossa referência material E, novamente, por preferência pessoal, sempre consigo um novo nó para extrair daqui, mas você pode simplesmente encontrar as informações dessa referência de material que acabou promover para uma variável. Vou pegar nossa referência de variável aqui e, a partir disso, quero encontrar o valor do parâmetro vetorial definido. Então, é essa opção aqui. Vemos que isso está na categoria de material, então estamos procurando a coisa certa. Isso nos permitirá definir a cor de um vetor, nesse caso. Então, vamos conectar isso ao pino de execução. O vetor que queremos alterar será a cor, então a cor emissiva E, novamente, podemos sempre verificar aqui. Isso é chamado de cor emissiva, então é o que eu estou procurando E a nova cor que eu quero que seja será baseada em qualquer ator que tenha gerado isso baseada em qualquer ator que tenha gerado Então, se for um inimigo verde, eu poderia transformar isso em verde. Se for nosso jogador, eu o transformo em azul. Se você tem um inimigo vermelho, talvez queira transformá-lo em vermelho. Então, vamos verificar se isso está funcionando. Se mudarmos isso para algo bastante óbvio, vamos deixar isso amarelo por enquanto, clicar em compilar e salvar Não vamos ver isso acontecer até começarmos a jogar. Então, podemos colocar isso no gráfico e clicar em simular aqui Devemos ver isso começar a brilhar. Outro problema que acho que tenho aqui é com o projétil MI underscore Quero ter certeza de que isso está marcado. Mas também preciso ter certeza de que isso tem alguma propriedade emissiva Então, vou entrar e me certificar de que o valor padrão para a propriedade emissiva aqui é dez Porque, novamente, estamos multiplicando isso no momento, qualquer cor por zero fará com que ela não Então, se pressionarmos Play novamente ou simularmos, na verdade, podemos ver que agora ficou amarelo Então, se eu me aproximar um pouco mais, clicarei em simular para que possamos ver tudo e teremos um projétil amarelo brilhante Portanto, a única alteração que você deseja fazer é abrir o material e garantir que ele brilhe o quanto quiser Você pode fazer com que seja muito mais exagerado, então podemos fazer disso um projétil muito brilhante e brilhante, dependendo totalmente Então, vou definir isso para 100 para que fique muito, muito visível. E isso é basicamente o que fazemos aqui. Então, estamos pegando essa propriedade pelo nome e definindo-a com um novo valor, simples e simples Agora, outra coisa que você pode querer fazer é ter um pouco de brilho mais do que outros. Então, eu só precisei entrar e editar manualmente a intensidade emissiva aqui Então, o que poderíamos fazer em vez disso é mostrar como podemos usar esse sistema. Podemos duplicar a referência do material e, desta vez, vou definir um valor escalar Portanto, os valores com os quais estamos trabalhando, embora sejam conhecidos como flutuantes, quando trabalhamos com materiais, infelizmente, são chamados de escalares Isso ocorre porque eles são feitos de um flutuador escalável. Podemos alterá-los em tempo de execução. Então, tente se lembrar disso. É uma terminologia um pouco nova, mas que você precisa aprender para trabalhar com materiais especificamente Então, vamos pegar nosso valor escalar. Essa eu chamei de força emissiva. Então, vamos conectar isso. encontrar nossa força emissora E então você pode mudar isso para qualquer valor que você queria que fosse. Então, poderíamos transformar isso em algo realmente tolo por padrão, como 1.000 Então, 1.000 pode ter sido um pouco extremo, mas mostrou o conceito geral. Vou reduzir isso para 100. Acho que parece muito legal, pois propriedade um tanto emissiva um projétil que se move bem rápido Talvez precisemos enfatizar isso para torná-lo mais visível. Como em tudo, não queremos que essas sejam variáveis mágicas novamente. Só poderíamos mudar isso aqui diretamente no código. Então, vamos promover nossa cor para uma variável que podemos rastrear e usar posteriormente. Estamos nomeando essa cor de projétil pelo nosso valor. Então, o valor do ponto flutuante aqui. Vamos transformar isso em uma variável e chamá-la emissiva de um projétil Então, isso nos dará alguma flexibilidade quando começarmos a gerá-los em nossas classes principais, inimigo ou no jogador Agora, alguns de vocês podem ter percebido que há outro problema que ainda não abordamos. E isso é que os projéteis podem potencialmente voar no espaço para sempre se não atingirem absolutamente nada Pensei que, se as coisas atingirem o chão e as paredes, eu disse que elas simplesmente se limpariam sozinhas. Acione uma função descartável muito barata, que é perfeitamente adequada para causar danos na parede, que basicamente será ignorada, mas não consideramos o que acontece se ela não atingir absolutamente nada O que eles farão no momento é voar para a eternidade, devorando a memória Portanto, há duas coisas que poderíamos fazer. A primeira é que, se conquistarmos nossa propriedade principal aqui, podemos realmente dar a qualquer ator com quem trabalhamos uma vida inteira. Então, vou encontrar isso no painel de detalhes. Podemos pesquisar aqui por toda a vida, e podemos dar a isso uma expectativa de vida inicial. Se soubermos que isso definitivamente não ficará na tela por mais de, digamos, 10 segundos, então podemos dar a isso uma vida útil de dez segundos E depois desse tempo, se não tocar em nada, se não chamarmos a função de destruição aqui, ela será destruída automaticamente. O problema aqui é que podemos acabar com alguns projéteis que se movem um pouco mais devagar do que outros, ou vamos usá-los e talvez reciclá-los mais tarde, que significa que podemos simplesmente escondê-los e trazê-los de volta ao jogo E, obviamente, não queremos que nossos projéteis simplesmente saiam da tela aleatoriamente em 10 segundos Então, na verdade, não vou usar essa abordagem. Outra coisa que você pode ver é no evento, uma verificação constante para ver se ele está fora da câmera ou fora da zona E vamos fazer algo um pouco semelhante, mas eu queria me concentrar novamente nas boas práticas de programação. Como eu disse, algumas coisas definitivamente podem e devem estar no Tick, mas isso não é uma das coisas que vamos fazer é criar uma nova função chamada out of bounds check E isso vai ser uma matemática muito, muito simples. Então, vamos clicar com o botão direito do mouse e pesquisar a localização do ator G, a localização do projétil em seu ponto atual Vamos extrair desse nó e retirar outro vetor. Então, vamos subtrair um nó aqui e podemos usar algo chamado gerenciador de câmera do player Portanto, se obtivermos o gerenciador de câmeras do player, podemos encontrar o premade sempre meio que referenciado e na memória Unreal de qualquer maneira, então também podemos fazer uso desses valores que já existem E a partir do gerenciador de jogadores, o que atualmente está rastreando a câmera ativa atual, podemos obter a localização da câmera. Então, essa será a localização atual da câmera que estamos vendo. Então, podemos retirar esses dois, e isso fornece um novo vetor, uma distância para nós. A partir disso, podemos puxar o pino vetorial aqui e queremos obter o comprimento do vetor. Então, se procurarmos o comprimento, podemos obter o comprimento vetorial. Isso converterá isso em um valor de ponto flutuante para nós, essencialmente nos dando uma distância em linha reta. Portanto, sabemos exatamente quantas unidades em linha reta nosso projétil atual está longe de nossa câmera Isso funciona independentemente da direção, o que é outra coisa muito útil desse tipo de abordagem, que significa que funcionará para projéteis voando em qualquer direção, em qualquer ângulo E então o que queremos fazer é, a partir do nosso pino de execução , retirarmos daqui e obteremos uma ramificação. Você tem espaço suficiente para trabalhar com isso. E basicamente vamos dizer que, se esse comprimento vetorial for maior ou igual a um determinado valor, então vamos destruir esse ator. Então eu digo mais do que ou igual a para contabilizar, novamente, se ultrapassar esse valor. Se isso for verdade, vamos conectar isso aqui, secar um pouco as coisas aqui. E vou dar isso, acho que um valor de 3.500 unidades funciona Então, isso está aproximadamente fora das zonas da câmera. Podemos ser um pouco mais científicos e tentar testar isso mais tarde. Se você achar que as coisas estão saindo da tela muito cedo, basta aumentar esse valor e, se as coisas estiverem demorando muito, você poderá diminuí-lo. Mas acho que isso definitivamente funcionará. Não importa se eles existem por alguns segundos a mais do que deveriam. O principal é que não queremos vê-los simplesmente tela e desaparecendo magicamente E não queremos que centenas e centenas de projéteis existam por minutos a fio Esse é mais um problema que estamos tentando resolver. Se isso for verdade, então vou partir daqui, vou dizer destruir o ator só para que possamos limpar aquele projétil da memória Tão bonito e simples. Como sempre, não há números mágicos, então vou descer e promover isso como variável. Vamos chamar isso de algo como distância fora dos limites. E, novamente, isso torna simples e agradável que sempre possamos voltar direto para cá. E se estamos tendo problemas em que precisávamos mudar isso, aumentá-lo ou diminuí-lo, agora temos um bom lugar fácil de encontrar um lugar para fazer essa mudança. No momento, não chamamos essa função, então um problema muito simples de resolver ou fácil de ignorar é que não podemos simplesmente criar a função Precisamos ligar para isso também. Não queremos ligar para isso apenas uma vez. Obviamente, não gostaríamos de fazer isso no início do jogo. E, como mencionei, não queremos fazer isso constantemente em eventos Então, em vez disso, o que vamos fazer é a partir do pino de execução, depois de definir nosso parâmetro escalar aqui, vamos, mais uma vez, fazer uso de temporizadores Isso é muito, muito flexível. Então, procuraremos a mesma função, que é definida como temporizador pelo nome da função A função que queremos obviamente será nossa verificação fora dos limites Então, novamente, vou renomear isso, na verdade, renomeá-lo, mas pressione Control C, Control V para colocar isso, e poderíamos configurá-lo para repetir talvez uma vez a cada segundo Portanto, lembre-se de que, se fizéssemos isso no Tick, isso seria verificado potencialmente 120 vezes por segundo com base na minha taxa de quadros atual. Então, isso é um pouco exagerado. Não precisamos que seja tão preciso. Fazer isso uma vez a cada segundo não vai sobrecarregar o desempenho do jogo, e isso significa que ainda estamos verificando, em uma iteração ou intervalo relativamente rápido , os projéteis que não precisam estar Como mencionei, ter um projétil por mais alguns segundos não será potencialmente ter centenas de projéteis sendo verificados 120 vezes por segundo; se eles ainda existissem, seria mais problemático Queremos ter certeza de que isso seja chamado continuamente, mais de uma vez, então definiremos isso como loop Então, uma vez a cada segundo, isso agora será chamado. Temos uma iteração em loop desse cronômetro, que verificará localização do projétil contra a câmera e se ele está tecnicamente fora de vista Então, podemos ir e testar isso. Se conectarmos um desses, criaremos talvez alguns deles e clicaremos em simular para que possamos ver o disparo E você pode ver que um deles realmente atingiu o avião inimigo, que foi destruído ao atingir o avião Mas o outro dispara e, depois de estar uma certa distância, não o vemos mais. Então, se eu pressionar o avião a partir daqui, o principal é que não os vimos simplesmente desaparecerem pela câmera, é isso que queremos evitar. Mas sabemos pelos testes anteriores que eles estão sendo eliminados quando testamos isso no modo de simulação Claro, eles estão voando e saindo da visão da câmera Então, essa é uma boa maneira limpa de fazer isso. Isso não vai fornecer uma grande sobrecarga. Isso definitivamente não causaria problemas de desempenho. É um cálculo relativamente simples e leve aqui. Acho que é muito mais seguro do que usar a vida útil, porque não sabemos por quanto tempo ou com que velocidade todos os projéteis se moverão e por quanto tempo eles podem ficar na tela E isso é barato o suficiente para executar esse cálculo e não causará problemas de desempenho. E eu queria demonstrar apenas uma comparação simples de onde podemos usar o tick e onde evitamos usar o Tick. Lembre-se de que, quando estivermos brincando com essas coisas, sempre volte e exclua os atores que você talvez não esteja mais usando. Não queremos mantê-los por perto. Vamos criá-los a partir de alguma funcionalidade de disparo um pouco mais tarde Então, mais uma vez, se você ainda estiver brincando com essas coisas, sinta-se à vontade para experimentar velocidades diferentes, cores diferentes, ver se você deseja afetar alguma das outras propriedades na instância do material. Veja se você consegue descobrir como alterar alguns dos outros valores escalares ou parâmetros vetoriais Novamente, o principal é que você só precisa do nome e da grafia exata, e você ficará perfeitamente bem Você pode alterar os valores conforme achar melhor. Outro desafio interessante. Não, espero que você esteja se sentindo mais confortável com um pouco do programa Para adicionar aceleração ao longo do tempo com talvez algum tipo de interpolação Você pode ver essas abordagens no outro código que temos. E é uma das coisas boas que mencionei sobre a criação de nosso próprio código. É algo quase impossível de fazer com o componente de movimento do projétil Então, se você quisesse que ele passasse de uma velocidade mais lenta e acelerasse com o tempo ou ao contrário, você poderia começar a voar muito rápido e depois desacelerar, perdendo impulso Você também pode ver coisas como direcionar projéteis usando técnicas semelhantes, intercalando em direção a uma meta específica ao longo do tempo direcionar projéteis usando técnicas semelhantes, intercalando em direção a uma meta específica ao longo Eu mencionei que eu recomendaria manter a classe atual como está. Se você estiver fazendo esses testes e tentando alguns desses experimentos. Eu sempre recomendo duplicar o que você tem e tentar criar sua própria versão a partir disso No entanto, é uma ótima maneira de aprender. Não quero impedir que você experimente coisas novas, mas, é claro, nos tópicos futuros, usaremos esses projéteis exatamente como estão Portanto, eu também recomendo ter essa versão para que possamos concluir o projeto juntos. 21. 20 — Projeto: fogo do inimigo: Para fazer com que as coisas realmente disparem seus projéteis. Vamos fazer isso de novo, bem arrumado. Uma função de disparo na classe base personalizada pelas crianças, se necessário. mesmo padrão que usamos antes, então vamos acabar com a mesma funcionalidade do nosso projeto de exemplo, que estamos trabalhando para recriar um pouco, mas estamos adotando uma abordagem um pouco diferente Então, primeiro, apenas um lembrete, se você tivesse algum dos projéteis espalhados, eu recomendaria excluí-los Antes de começarmos, geraremos tudo isso dinamicamente em tempo de execução, quando necessário Vamos começar em nossa classe de avião base. Então, se formos para a base do plano central e fizermos nossa implementação inicial aqui, criaremos uma função aqui chamada fire. Faremos algo muito parecido com o que fizemos com nossa classe geradora inimiga Vamos retirar o pino de execução e procurar o ator de desova da classe Podemos, mais uma vez, partir daqui e promover isso para uma variável. E caso queiramos mudar isso mais tarde no momento, acho que teremos apenas uma única classe de projéteis Mas caso queiramos projéteis diferentes, vamos promovê-los para torná-los reutilizáveis Vamos renomear esta para classe de projéteis. Deixe isso como o tipo de ator padrão, clique em compilar e pronto. Agora, quando clicamos em compilar, recebemos esse erro dizendo que precisamos fornecer algumas informações extras Precisamos do TransponPin. Podemos fazer duas coisas. Podemos dividir o pino da estrutura. E se você quiser deixar isso completamente vazio, podemos clicar em compilar e isso fará com que o erro desapareça. Agora, vou pressionar Control in Dead. Há outra coisa que podemos fazer aqui. Para o local do spawn, precisamos saber exatamente onde queremos nossos projéteis venham a existir E uma maneira de fazer isso e tornar isso um pouco visual é adicionar um novo componente. Eu vou entrar no mirante. Vou adicionar um novo componente e selecionar o componente de cena aqui mesmo. Uma coisa que eu deveria ter feito era que isso já estivesse selecionando a malha, mas está tudo bem. Quero que esses componentes da cena sempre acompanhem o que está acontecendo com a malha. Então, vou pegar isso e soltar isso novamente, focando na hierarquia, para que o novo componente da cena seja filho da malha estática Para deixar isso claro, se você realmente quisesse, poderíamos renomear isso, e eu chamarei esse projeto de nosso local de desova Então, quando analisamos nossa hierarquia, temos uma ideia geral sobre o que esses diferentes componentes são responsáveis Agora, não precisamos que isso seja visual, mas o que podemos fazer com isso é que agora podemos movê-lo e ter controle direto de onde queremos que o projétil apareça Poderíamos ter isso um pouco na frente do avião. Bem, como mencionei, podemos querer que isso fique um pouco dentro do avião, para que não pareça que está surgindo magicamente do surgindo magicamente Quando você estiver satisfeito com a posição do local de geração do projétil, novamente, se clicarmos em compilar, obteremos esse resultado ruim do plano no visor, mas tudo bem Só queremos voltar à nossa função de bombeiros. Vamos controlar o arrasto local de geração do projétil até o solo Vou partir daqui e vou procurar algo chamado get world transform. Então, queremos essa opção aqui com a função verde? A transformação Get World fornecerá a transformação desse componente específico no mundo em relação à rotação e a tudo o que aconteceu. Assim, podemos garantir que o projétil esteja voltado para frente Vamos conectar isso, clicar em Compilar e podemos ver que os problemas desapareceram. Eu só queria mostrar outra coisa, e acho que pode realmente valer a pena mudar isso aqui de um ator para especificamente a classe baseada em projéteis Se voltarmos para nossa classe de projéteis aqui, clicaremos duas vezes para abrir a classe base e garantir que temos duas coisas expostas aqui Então, queremos que a cor do projétil seja exposta, a força de emissão do projétil e talvez a velocidade de movimento do projétil também possam ser Garantir que esses três sejam públicos. Você pode voltar e voltar, estou tentando estabelecer as bases para você. Você pode voltar e, depois ver o que estamos prestes a fazer, fazer as outras alterações que desejar. São totalmente opcionais, mas acho que esses três serão bons para testes. E se clicarmos em compilar e salvar, voltaremos para nossa classe base de avião e para a função de disparo Agora, por padrão, como isso é definido como um ator genérico, não há dados expostos. Agora, o que podemos fazer usando uma digitação específica é pesquisar nosso projétil de sublinhado BP Queremos usar a opção base, precisamos soltá-la e selecionar o tipo de referência da classe, não o tipo de objeto. Isso apenas nos dirá que algumas coisas precisarão mudar. Talvez tenhamos algumas referências ou links essencialmente quebrados para diferentes tipos de classes, e isso é perfeitamente normal. Digamos que mude essa variável. Vamos deixar isso funcionar. Realmente não vai quebrar nada porque, de qualquer forma, não estamos usando nada específico neste momento. Só tínhamos um ator genérico. Então, podemos fechar isso. E o que eu queria mostrar é que, se clicarmos com o botão direito do mouse no ator de spawn e escolhermos a opção refresh node aqui ou nos certificarmos de clicar em compilar primeiro, o que deveríamos ver são as propriedades que acabamos de expor, e acabei de perceber qual é o problema Há uma outra etapa que é muito fácil de ignorar. E vamos voltar para a base do projétil. Além de torná-los públicos , precisamos de outra caixa de seleção. Então, apenas algumas das coisas que você precisa saber sobre o Unreal, e você aprenderá isso à medida que avança Portanto, para a velocidade de movimento e as outras duas que expusemos, também queremos escolher essa opção aqui, expor no spawn no painel de detalhes Então, precisamos fazer isso para cada um deles, então pegue sua variável e marque a exposição em span Eu sugeriria que ele apenas expusesse essa propriedade sempre que geramos essa classe em Também é muito importante que tenhamos certeza compilar e salvar na classe projétil Caso contrário, se voltarmos para nossa base aérea, não veremos isso. E você pode ver agora que a principal razão pela qual queríamos isso é especificando que usaremos especificamente base de projéteis de sublinhado da BP vez Agora temos essas propriedades expostas, o que é muito útil. Isso nos dá o poder de mudar a cor com base na classe em que vamos gerar isso, bem como na velocidade de movimento, na força de emissão e coisas assim, dependendo de como você quiser bem como na velocidade de movimento, na força de emissão e coisas assim, dependendo de como você Com suas classes de projéteis. Agora, tudo isso é feito uma vez na classe base. Queremos que isso seja facilmente reutilizável sem precisar mergulhar Então, é claro, não vamos deixar esses números mágicos. Em vez disso, vamos promover cada um deles para uma variável. Promoveremos o primeiro, e chamaremos isso de velocidade de movimento do projétil E então, é claro, faremos a mesma coisa. Vamos promover a cor do projétil e a força de emissão do projétil em suas próprias propriedades . E está tudo pronto. Isso significa que agora podemos ter essa única função reutilizável avião do jogador e no inimigo do jogador, e tudo o que precisamos ajustar por classe é a rapidez com que queremos que os projéteis se movam Porque eu lembro que no projeto de exemplo, o inimigo é disparado mais devagar que o jogador, e podemos mudar a cor dependendo de quem está gerando Isso significa que não precisamos de muitos tipos diferentes de projéteis específicos Podemos simplesmente pegar nossa base de projéteis e fazer algumas mudanças rudimentares muito simples por avião A única coisa realmente importante antes de sairmos daqui lembrar que a funcionalidade da colisão que estamos fazendo é a seguinte: se estamos sobrepondo, no momento, nosso próprio dono, não queremos causar danos a nenhum Precisamos ter certeza de que o que está gerando a classe, o que estamos fazendo agora na base do avião, está realmente transmitindo as informações de quem é o proprietário Então, outra coisa que podemos colocar aqui no ator de desova na base do avião é o proprietário aqui Então, de forma simples e simples, podemos usar esse pino e procurar a referência G para vender. Ou você pode simplesmente digitar a palavra célula e verá obter referência a si mesmo aqui. Então, agora isso é apenas garantir que qualquer avião que gere esse projétil quando essa função for chamada, ele se marque esse projétil quando essa função for chamada, como o dono do projétil, garantindo que não cause danos a si mesmo garantindo que não cause Tão bonito e limpo, podemos bater e empilhar, economizar, e aquele está pronto para ser usado Então, agora estamos em um bom ponto em que podemos adicionar a versão mais simplista do disparo, que será nossa classe inimiga Antes de fazer isso, acho que há mais uma variável que ambas as classes poderão usar, que é a taxa de tiro, com que frequência o avião será capaz de disparar. Então, vamos criar uma nova variável aqui embaixo. O primeiro será do tipo de voo, então pressione Control ID em qualquer um dos outros voos, e eu chamarei isso de taxa de tiro. Ele compila. Acho que só para garantir que não esqueçamos de definir isso mais tarde, vou reduzir isso para zero e garantir que modifiquemos isso por plano. E então, a outra coisa que eu acho que será bastante útil em nossas duas classes mais tarde será um vetor dois D para a taxa de tiro mínima e máxima. Então, temos alguma randomização. Então, vou criar uma nova variável. Queremos que isso seja um vetor dois D novamente. Mas, por enquanto, chamaremos isso de taxa máxima de tiro de um mínimo. Queremos aquele vetor dois D que tínhamos anteriormente e, novamente, podemos deixá-los em zero por enquanto. Voltaremos e os modificaremos mais tarde. E esse é um daqueles casos em que obtemos muitas variáveis semelhantes para um sistema. Então, talvez queiramos colocá-los em uma categoria, especificamente para projéteis ou combates ou o que você quiser que seja Também poderíamos ter uma categoria de saúde, algo assim. Como mencionei, não vou continuar fazendo isso na tela, pois é apenas um trabalho árduo em segundo plano, mas definitivamente poderia ajudar, pois obtemos muito mais variáveis à medida que exibimos as classes individualmente. Mas isso é bom. Isso é bom para um ponto de trabalho básico, então agora podemos entrar em nossa classe inimiga, então vamos para o núcleo. Jogue como inimigo e queremos criar uma sequência no início do jogo. A razão para isso é que agora estamos tendo algum tipo de lógica confusa Estamos fazendo algumas coisas diferentes na inicialização de nossa classe, o que é perfeitamente normal, mas podemos simplesmente manter as coisas organizadas novamente Então, um truque rápido aqui é que podemos retirar o pino de execução após a chamada principal e entre o que já estamos fazendo, e chamaremos um nó de sequência aqui. E isso conectará automaticamente a lógica que temos sem quebrar nenhuma delas , então zero é essencialmente nossa inicialização para randomização genérica Então, poderíamos fazer um comentário dizendo: randomize os valores aqui. Então, a próxima coisa que vamos querer fazer é configurar nossos detalhes de disparo Então, na verdade, isso ainda será baseado em algum nível de randomização Então, vou clicar com o botão direito do mouse e obter a propriedade de taxa de disparo. Então, queremos definir a taxa de tiro aqui, e ela será novamente definida em uma flutuação aleatória no alcance Vamos conectar isso, e esse flutuador aleatório, é claro, será o mínimo que acabamos Então, obteremos a taxa de tiro máxima mínima, dividiremos o pino da estrutura como fizemos antes e os conectaremos aqui. Então, mínimo, máximo para o X e o Y. Então, outra boa randomização simples para que todos os inimigos não atirem exatamente na mesma velocidade e, caso contrário, pareça muito repetitivo e Se clicarmos em compilar, também queremos ter certeza de que, para a classe inimiga, definimos uma taxa de tiro Minimax, que acho que talvez esteja entre 0,4 e 0,8 Novamente, você pode ajustar todos esses valores conforme desejar e, em seguida, a taxa de tiro será definida especificamente entre esse intervalo Então, a partir da segunda saída e agora que fizemos nossa randomização, podemos realmente começar a configurar a funcionalidade de disparo a ser chamada Então, vamos usar o cronômetro definido pelo nome da função novamente, a partir daqui Vamos usar o cronômetro definido pelo nome da função. Claro, vamos chamar a função de fogo. Isso criamos em nossa classe base, e o tempo será nossa taxa de tiro. Então, obteremos a taxa de tiro que acabamos de randomizar e garantiremos que ela esteja configurada para um loop Portanto, isso continuará sendo chamado enquanto o inimigo estiver em jogo. A randomização garante que cada inimigo atire em sua própria taxa aleatória Alguns serão um pouco mais agressivos e outros mais descontraídos Outra coisa para os inimigos é que, ao saírem da tela, se o jogador errar, como acontece com os projéteis, eles também devem estar se limpando Então, vamos entrar na classe de projéteis e, na verdade, vou usar a lógica exata de verificação fora dos limites aqui Podemos copiar tudo isso, pressionar control NC, voltar para a classe inimiga Criaremos uma nova função. Novamente, vamos chamar isso de fora da verificação dos limites E nós apenas colamos isso no gráfico aqui. Então, um pouco de duplicação. E, novamente, é aqui que você pode começar a considerar coisas como o uso de componentes seria algo valioso aqui. Você pode ver que, ao se aprofundar na programação, o conceito geralmente chamado de herança versus composição, fazendo uso de componentes como esse Um pouco fora do escopo desse sistema realmente introdutório Então, usaremos um pequeno atalho para algumas coisas , mas essa ainda não é uma abordagem terrível para fazer isso, apenas uma pequena duplicação Mas a variável de verificação fora de banda aqui que copiamos da outra classe obviamente não existe aqui, então vamos clicar com o botão direito do mouse e criar uma variável E neste, acabamos de clicar em Compilar. Vamos verificar a localização do inimigo pela câmera. Para a distância fora dos limites, podemos usar um valor similar Acho que 3.500 estavam funcionando muito bem. Só queremos ter certeza de que estamos de olho nos inimigos que saem da área de jogo e, se percebermos que eles estão simplesmente desaparecendo, talvez queiramos ajustar isso de alguma forma Agora, com isso pronto, queremos voltar ao nosso gráfico de eventos. Talvez queiramos começar a arrumar um pouco as coisas e apenas movê-las para nos dar espaço O principal aqui é que poderíamos configurar outra hora aqui, então essa pode ser nossa lógica para configurar as funções recorrentes Então, criaremos outro TO pelo nome da função para este. Essa será nossa verificação fora dos limites, e talvez queiramos fazer isso uma vez a cada segundo Então, vamos definir um horário aqui , mas uma vez a cada segundo. Vamos promover isso para variável. E vou configurar este para ser chamado fora da duração da verificação de limites Como antes, clicaremos em Compilar. Queremos ter certeza de atribuir a isso um valor, de modo que seja 1 segundo, e definiremos isso como loop, para que continue continuamente até que seja removido do Como eu fiz no passado, também. Acho que vou escrever clique aqui e encontre a função de disparo. Então, vamos apenas chamar FireFunction. Na verdade, não vamos usá-lo. É só para que, novamente, se quisermos verificar o que está acontecendo dentro dessa função, podemos clicar duas vezes aqui. Vou pegar o cheque fora dos limites, obter o nome e garantir que preenchamos isso aqui em nosso tempo e, em seguida, arraste-o pelo mesmo motivo novamente Caso eu queira ver o que está acontecendo, posso clicar duas vezes e ver o código exatamente. Como mencionei, é apenas uma preferência pessoal, mas algo que sempre costumo fazer em meu próprio código. Uma última coisa que acho que esquecemos de fazer é porque trocamos um pouco as classes de projéteis Se voltarmos para a classe base em que implementamos a função de fogo, se pegarmos nossa classe de projéteis aqui, podemos ver que a classe está Então, se tentássemos isso agora, não conseguiríamos que nenhum inimigo realmente disparasse nada porque eles não o tipo específico de classe para atirar Então, no momento, só temos uma, que é a classe base. Mas se fizéssemos algumas aulas para crianças a partir disso, também poderíamos usar essas versões exclusivas. Então, enviamos isso para ser a base padrão de projéteis porque, no momento, é a única coisa com a qual temos que trabalhar Clique em compilar e salvar. E então, no inimigo, o que você verá é que isso se propagará automaticamente. Portanto, também temos a classe de projéteis definida aqui. Clique em compilar e salvar, e podemos aninhar o inimigo atirando. Então, nada muito sofisticado, mas eles são de fato. Atirando e podemos ver que obtemos isso em taxas diferentes, velocidades diferentes Portanto, temos uma jogabilidade um pouco única dos diferentes inimigos. Devemos também observar que após um certo número de golpes, o jogador deve ser retirado do jogo, para que o dano funcione automaticamente. Portanto, temos tudo funcionando conforme o esperado, pelo menos para a classe inimiga, o que é ótimo. A última coisa que notei é que provavelmente será um pouco rápido, e tudo bem. É por isso que definimos que todos esses valores sejam expostos para que sejam fáceis de ajustar e alterar com base nos testes de jogo, feedback e no campo geral do jogo que você pode estar buscando Então, acho que no inimigo, vamos diminuir um pouco a velocidade de seus projéteis , porque haverá muitos deles. O jogador provavelmente quer atirar mais rápido e os inimigos podem ficar um pouco mais relaxados. Então, vamos definir isso para algo como 1.500. E se acharmos que isso é muito lento. Então, estou apenas selecionando aqui na classe inimiga, pegando a velocidade de movimento do projétil e reduzindo-a para 1.500 Também podemos mudar a cor. Então, meus inimigos são verdes. Vou pegar uma cor que esteja um pouco mais próxima do estilo inimigo aqui. Você deve ser capaz de usar o seletor de cores que possamos entrar na cor, obter o seletor de cores e clicar na parte do plano que deseja combinar com a cor Para mim, isso não está funcionando. Isso é selecionar a correspondência estática. Então, vou pegar uma cor que é mais ou menos semelhante ao corpo do avião. Isso seria perfeitamente bom, eu acho. Então, novamente, se clicarmos em compilar, temos projéteis se movendo em velocidades diferentes e, na verdade, eles representam a cor da nave, que os está disparando Você também pode alterar coisas como a força emissiva se não quiser que elas brilhem ou se quiser que elas brilhem mais ou menos Mas é isso. Então, esses são os inimigos configurados e prontos. Apenas uma pequena tarefa paralela para você pause o conteúdo novamente entre os tópicos e talvez comece a analisar diferentes variáveis que você acha que podem funcionar para a taxa de tiro mínima e máxima Talvez você não esteja sentindo diferença suficiente entre os diferentes inimigos à medida que eles aparecem Talvez mude a cor, os diferentes tipos de velocidade de movimento, o dano causado, exponha outras variáveis, brinque com todos os valores aos quais você agora sabe que tem acesso A seguir, daremos uma olhada na funcionalidade de disparo do jogador. Vai ser um pouco diferente, um pouco mais prático, mas você pode ver que já temos uma base muito boa sobre a qual construir. 22. 21 — ProjectileFire Player: Agora pode ir direto para fazer que o jogador atire de forma semelhante ao inimigo Então, vamos reutilizar parte dessa lógica básica, propriedades expostas do projétil, e ter um controle um pouco mais refinado sobre se e quando o jogador deve atirar Então, se entrarmos e abrirmos o player de avião de sublinhado da BP, temos duas opções diferentes Agora, uma é que muitas pessoas podem simplesmente colocar a funcionalidade principal fora das funções em seu gráfico de eventos principal. Outra coisa que eu queria apresentar, porém, é que podemos criar nossos próprios gráficos personalizados Portanto, o gráfico de eventos padrão vem com coisas como o início do jogo, os eventos, aquelas coisas incorporadas ao mecanismo por padrão. Perfeitamente bem. Uma coisa que eu gosto muito de fazer é pressionar esse botão de adição aqui e criar um gráfico totalmente novo. Vou dar o nome dessa nova entrada gráfica. E será aqui que colocaremos toda a nossa lógica especificamente com base no recebimento de informações para o jogador. Então, novamente, começamos a adicionar coisas mais tarde, como um botão de reinicialização ou um botão de menu ou diferentes tipos de power-ups e outras coisas Todas essas entradas podiam ser rastreadas aqui em um local agradável e conveniente Para registrar a entrada de incêndio, finalmente usaremos um evento de entrada. Então, anteriormente, usávamos apenas as variáveis que são armazenadas em coisas como o sublinhado IA em nosso movimento de alça que vimos aqui Portanto, este é nosso exemplo de usar apenas o valor flutuante retornado Dentro do gráfico de entrada, clicaremos com o botão direito do mouse e procuraremos por IA underscore Fire E vemos que temos a opção aqui, na verdade, queremos fazer uso desse evento que é retornado. Portanto, sempre que o botão de disparo é pressionado, podemos fazer com que algo aconteça com o resultado acionado da entrada recebida. Agora, a primeira coisa que sempre queremos considerar é que queremos um feedback imediato, algo que é mais do lado do design de jogo e da teoria, é que, quando o jogador pressiona algo, ele tem a expectativa de receber um feedback imediato Não há atraso entre eles pressionarem algo e algo acontecer Então, por esse motivo, assim que a entrada for recebida, queremos ter certeza de que algo comece a acontecer. Portanto, temos vários eventos diferentes que são acionados aqui e queremos usar o Started antes de tudo. Portanto, queremos ter certeza de que a função de disparo seja chamada imediatamente no Início. Vamos chamar aqui a função de fogo da nossa turma principal. Podemos ver que essa é a classe base. Iniciado é chamado imediatamente assim que o pressionamento do botão for reconhecido e, em seguida, concluído, será acionado assim que o botão for solto. Portanto, podemos usar esses diferentes estágios do pressionamento do botão, mas o importante por enquanto é que fogo seja acionado imediatamente. Depois que a primeira função de disparo for chamada, retiraremos o pino de execução e criaremos outro cronômetro definido pelo nome da função A função, claro, será fogo. Principalmente por causa do hábito aqui. Vou apenas duplicar a função de disparo que já temos e, novamente, vou colocá-la abaixo do cronômetro porque sabemos que é a que estamos usando aqui A quantidade de tempo entre isso, vamos sair daqui e eu vou encontrar nossa taxa de tiro. Então, vamos obter o valor da taxa de tiro. E acho que para o jogador, embora eu tenha dito, talvez queiramos considerar a randomização, essa é outra daquelas coisas agora, quando se pensa em coisas mais do que um princípio de design Provavelmente queremos definir isso, em vez de definir um mínimo e um máximo, o jogador terá a expectativa de que toda vez que atirar e toda vez que jogar, sua taxa de tiro seja a mesma A menos que você esteja criando algo como um ladino, dizendo especificamente ao jogador que, com base em seu personagem ou em estatísticas aleatórias, a taxa de tiro pode ser Nesse tipo de jogo, eles esperam que sempre pareça o mesmo para que possam se acostumar com a mecânica e aprender a Então, se clicarmos em compilar, pegaremos a taxa de disparo e definiremos isso para 0,2 Vamos nos certificar de configurar isso para ser repetido. Então, basicamente, o que estamos dizendo é que pressionaremos fogo e, quando você segurar o botão, chamaremos essa função para que , quando estiver segurando, continue atirando Então, podemos voltar aqui e agora podemos fazer uso dessa função completa. Então, como mencionei, isso é chamado quando você solta o botão que está segurando. Então, depois de concluído, podemos realmente usar outra parte do tempo de funcionalidade incorporado, e essa é uma maneira muito boa de manter seu código novamente limpo e organizado Você pode ter visto em outros exemplos isso associado ao evento com alguns atrasos, que pode ser muito confuso se você pensar em executar um evento e um atraso juntos, combinando essencialmente a lógica, que serve para ser executada constantemente em um determinado intervalo, e também tentar atrasá-la enquanto a enquanto Então, vamos evitar códigos desleixados como esse. Em vez disso , vamos encontrar uma função chamada clear Tir pelo nome da função. Então, vamos usar essa função aqui, e isso é muito bom e simples. Vamos pegar nosso nome de fogo aqui, então vamos pegar o texto aqui e depois colá-lo aqui. Portanto, agora temos controle total sobre quando isso começou e quando termina. Então, na primeira vez que pressionarmos o botão de disparo, chamaremos a função de disparo. Em seguida, também garantiremos que continuemos lembrando isso enquanto estivermos pressionando o botão Mas se quisermos que isso pare, assim que reconhecermos que o botão foi liberado, vamos limpar o nome dessa função, ou seja, essa função de cronômetro Então, ele vai encontrar isso porque eles compartilham o mesmo nome. Isso cancelará o loop aqui, e isso significa que não vamos mais atirar Portanto, não temos fios em todos os lugares, coisas que tentam se cancelar no evento funcionam. É apenas um único evento de incêndio, e estamos adicionando apenas uma pilha a cada 0,2 segundos. Chame uma função muito simples. Então, novamente, sobrecarga muito baixa, muito bom para desempenho, muito limpo ler e muito mais fácil de gerenciar E, na verdade, para o jogador, restam apenas algumas coisas aqui. Portanto, a funcionalidade de disparo é relativamente simples. Só queremos entrar nos detalhes da aula aqui e fazer algumas mudanças semelhantes às que fizemos antes. Então, a velocidade de movimento do projétil, eu acho, 2.500 para o jogador é boa Deixe que a emissiva esteja perfeitamente bem. E vamos apenas mudar a cor. Meus jogadores têm uma cor meio azulada, então vamos embora. Com isso aqui. Talvez tente combinar isso um pouco mais. Como mencionei, em seu sistema, talvez você consiga usar o seletor de cores Mas para mim, isso é apenas selecionar preto. Então, vou definir isso de uma forma mais manual. Podemos então clicar em compilar, salvar e, em seguida, podemos entrar e testar isso Aí está. Assim, o jogador tem feedback contínuo ao pressionar o botão. Isso ocorre continuamente até soltarmos o botão de disparo Então, como eu mencionei, muito bom e limpo. Se você nunca viu isso antes, não vou encontrar tutoriais específicos para destacá-los, mas dê uma olhada no YouTube antes de algo como o Unreal Engine, mas dê uma olhada no YouTube antes de algo como o Unreal Engine funcionalidade de fogo de projeto ou a lógica do tiroteio, algo genérico como esse e veja Fique atento especificamente a eles, que o levarão ao evento. Reduza alguns atrasos com base na taxa de tiro e veja como eles usarão coisas como portões para cancelar a chamada da função de disparo quando um botão for pressionado ou solto taxa de tiro e veja como eles usarão coisas como portões para cancelar a chamada da função de disparo quando um botão for pressionado ou E então compare isso com o que acabamos de fazer aqui com duas chamadas muito simples para iniciar a função e finalizá-la ao longo do tempo Novamente, como mencionei, com exemplos épicos e coisas assim, isso nunca significa chamar a atenção de outras pessoas ou projetos. Explicitamente. Definitivamente, o Mcde nem sempre é o melhor, mas é só para fazer você pensar e realmente criticar o que está vendo enquanto aprende, porque uma das piores coisas que você pode fazer é seguir tudo cegamente e presumir que é sempre a melhor ou a Sempre haverá maneiras diferentes de abordar um problema, e eu só quero que você pense se o que você está fazendo em seus projetos ou o que você está vendo on-line é uma forma que você deseja implementar em seus próprios projetos para torná-los gerenciáveis e fáceis de trabalhar É basicamente isso para projéteis. Novamente, certifique-se de verificar se tudo tem os valores precisos preenchidos se quiser as etapas extras que você poderia seguir para melhorar seu projeto. Vou deixar isso em paridade com o projeto de exemplo, mas temos problemas que podem não ser facilmente perceptíveis, mas eles definitivamente existem Por exemplo, podemos, na verdade, clicar no botão de disparo de spam mais rápido do que a taxa de disparo. é muito difícil de fazer porque defini De qualquer forma, é muito difícil de fazer porque defini a taxa de tiro relativamente rápida, mas você pode ver que estou clicando aqui mais rápido do que se eu simplesmente aguentasse. Então, talvez considere como você pode consertar isso sozinho. Eu não vou passar por esse processo. Seria essencialmente o caso de rastrear um valor em talvez um cronômetro separado quando você pressiona o botão pela primeira vez Na próxima vez que você pressionar o botão, se for menor do que a taxa de disparo definida , você simplesmente cancelará a chamada da função de disparo. Nesse caso, não é um projeto tão complexo que eu realmente ache que faça uma grande diferença. E, como mencionei, essa mesma funcionalidade está no projeto de exemplo com o qual estamos tentando atingir a paridade de qualquer maneira Mas é apenas um bom tipo de prática mental e veja se você consegue pensar em como incorporar uma lógica semelhante, mas impedindo o jogador de clicar e atirar mais rápido do que a taxa de tiro especificada Nossos principais próximos passos, porém, são que os navios estão armados. O jogador e os inimigos estão atirando, ambos usando cores e taxas de tiro diferentes Você também pode ajustar esses valores novamente. Se você achar que o jogo é muito difícil ou muito fácil, mude coisas como o dano, que é aplicado com base na origem dos projéteis disparados, nas taxas de tiro e coisas assim Em seguida, voltaremos a usar nosso gerador genérico de atores. E vou começar a adicionar alguns planos de fundo rolantes para fazer com que as coisas pareçam um pouco mais interessantes 23. 22 - RolagemFundos Fundo: É hora de levar esse projeto um pouco mais longe e realmente fazer com que pareça um jogo. Vamos adicionar um pouco de água, algumas ilhas rolantes, e faremos isso reutilizando nosso sistema Spanus, é por isso que o construímos para ter uma configuração tão Podemos encerrar qualquer uma das aulas que temos no momento. Clique com o botão direito na guia principal e selecione fechar outras guias, e isso eliminará tudo o que você não está usando no momento, e então podemos simplesmente fechar o player De volta à inicialização da visualização principal, queremos usar o botão Adicionar aqui e adicionaremos um plano simples. Então, se formos para as formas e pudermos encontrar um plano, queremos apenas que seja uma superfície plana. Vamos redefinir a localização, então definiremos isso como zero clicando no botão desfazer aqui Pressione o botão de bloqueio para garantir que isso seja dimensionado uniformemente e, em seguida, definiremos o valor para algo como 80 para garantir que cobriremos toda a zona de jogo, ou seja, tudo o que podemos ver Também podemos nos livrar do chão. Anteriormente, usávamos isso apenas para contextualizar, para que possamos ver exatamente para onde e quando estamos nos movendo. Estamos usando essa grade essencialmente para detectar movimento. Não precisaremos mais disso, então podemos nos livrar da localização real do próprio avião. Queremos que isso seja menos 4.000 no z. E, novamente, isso se baseia apenas em como eu tenho minha câmera configurada, avião e na localização do inimigo Você pode achar que seu nível tem uma configuração um pouco diferente, mas se estamos partindo de um projeto mais ou menos semelhante por enquanto, você pode ajustá-lo mais tarde Estar tão baixo mantém as sombras um pouco mais sutis e nos dá espaço para as ilhas flutuantes, porque alguns dos objetos que forneci são intencionalmente muito grandes Da pasta, vamos para nossa pasta de ativos. Vamos encontrar os materiais, e podemos encontrar a água do sublinhado MI e simplesmente arrastá-la para o avião Então, isso nos dará um material aquático animado, simples e básico. Como mencionei, alguns detalhes e propriedades podem precisar ser alterados aqui, como o tamanho do avião ou a localização. fazemos um tipo completo de varredura e refinamento quando chegamos ao final do tópico , com base na aparência das coisas Se você quiser trocar sua água, novamente, podemos clicar duas vezes no material aquático MI underscore Arraste isso para a janela aqui. Essa é uma boa maneira de, mais uma vez, fazer uso da instância material. Se você achar que a água fluindo muito rápido ou não gostou da cor, podemos receber esse feedback ao vivo mesmo enquanto jogamos para ver exatamente o que você queria fazer com coisas como o desvanecimento da profundidade, a distância, as diferentes propriedades da cor e coisas assim Assim, você tem controle total sobre a aparência da água. Vou manter isso como está, mas só para dizer que esses valores estão aqui se você quiser ajustá-los. Em seguida, queremos considerar nossas ilhas. Então, vamos voltar para nossa pasta Blueprints. Criaremos uma nova pasta aqui. Vamos nomear essa ilha. Dentro da pasta das ilhas, vamos clicar com o botão direito do mouse, ir para a classe Blueprint e criar um novo ator Só precisamos de algo com presença no mundo novamente, e chamaremos isso de BP Underscore Island Dentro da classe, configuração muito padrão agora. Vamos adicionar uma nova malha estática. Definiremos isso como a raiz de cena padrão, então substituiremos a raiz de cena padrão aqui E com a malha estática selecionada, vamos para o painel de detalhes. Encontraremos a ilha de sublinhado SM redonda, então a maior para começar Podemos pressionar F no ponto de vista, para que possamos ver como seria a ilha E então nós só queremos ir até as propriedades da colisão, e vamos ver os detalhes da colisão Vamos deixar isso no chão e definir isso para não colidir. Desativaremos a geração de eventos de sobreposição. Apenas certifique-se de que isso não tenha física, não tenha verificações de sobreposição Esse será um objeto descartável muito barato, que existe apenas para Agora, antes mesmo de começarmos usar nosso gerador para trazê-los ao mundo, sabemos que isso vai parecer muito repetitivo, muito chato Vamos obter a mesma malha estática com o mesmo tamanho, a mesma rotação toda vez que uma for gerada Vamos começar o jogo e resolveremos isso imediatamente Da mesma forma, vamos nos livrar da chamada da função Actor start overlap Queremos começar a jogar aqui, e podemos fazer algumas coisas simples a partir do pino de execução aqui. Então, primeiro de tudo, podemos randomizar um pouco a escala do ator Então, chamaremos o conjunto de escala de ator de três D. E vamos fazer isso de uma forma um pouco estranha Mas se clicarmos com o botão direito do mouse e pesquisarmos por flutuação aleatória no intervalo, podemos definir esse intervalo mais uma vez com base em um vetor dois D. Então, criaremos uma nova variável Chamaremos isso de escala Min Max. Largue isso, encontre o vetor dois D. Ele compila e fornece alguns valores aqui para talvez algo como 0,8 a 1,2 Coloque-os como fizemos antes. Então, você pode ver que, novamente, estamos chegando ao ponto muitos códigos se tornarão muito familiares. E essa é a ideia de repetição. Vamos deixar você mais confortável com o projeto e com o Unreal. Então, vamos dividir a estrutura em. Vamos conectar isso ao mínimo e ao máximo. E podemos, na verdade, pegar nosso valor flutuante aqui e convertê-lo em um vetor Do jeito que isso funciona, pode parecer um pouco estranho como estamos usando um flutuador ou um vetor Basicamente, vou garantir que o X, o Y e o z obtenham qualquer que seja esse resultado. Portanto, se escolher 1,1, significa que X, Y e Z serão todos definidos como 1,1 Agora, se você quiser esticar as coisas , tenha um controle mais refinado. Obviamente, você sabe que pode dividir o pino da estrutura do vetor e talvez fazer uma flutuação aleatória no X, no Y e no z individualmente O problema que eu acho com isso é que você realmente não tem um controle muito refinado sobre como impedir que a malha fique completa. Você pode acabar com algo como muito estranho e esmagado ou muito estranho e esticado. Então, por esse motivo, vou definir isso para ser uniforme, então é só escalar todos os eixos juntos. Então, também podemos pegar nossa malha estática. Vamos colocar isso no gráfico de eventos e extrair nossa referência de malha aqui, então, uma referência ao nosso componente, procuraremos a função de malha estática definida. Queremos este aqui, aquele que nos dará o componente de malha, só para ter certeza de que você viu que queremos ir para a malha estática dos componentes e definir a malha estática. Não esse aqui. Na verdade, isso é atualizar a variável em si, enquanto isso está pegando o componente que temos e acessando os detalhes por meio de nosso painel de detalhes aqui. Então, talvez também queiramos randomizar a malha estática que usamos Então, podemos começar a partir daqui. Você provavelmente tem uma ideia para onde isso está indo porque, novamente, já fizemos isso várias vezes antes. Só temos duas opções estáticas diferentes para as ilhas Então, vou usar um nó de seleção. E como temos apenas dois, a maneira mais fácil ver isso é se tivéssemos mais, talvez queiramos usar algum número inteiro aleatório dentro de um intervalo e, se tivéssemos cinco, escolheríamos um intervalo de 0 a 4 ou um , cinco, E dependendo do que foi escolhido entre esse intervalo inteiro, ele escolheria um dos quatro ou cinco modelos diferentes Agora, como só temos dois, vou usar um booleano Vou escolher uma bola aleatória aqui. Nem precisamos que isso seja uma variável. E então temos basicamente 50% de chance de desovar na ilha grande ou na ilha pequena Então, simples e simples, não precisamos tornar isso muito complexo, pelo menos agora estamos recebendo alguma randomização Podemos gerar a mesma ilha grande três vezes seguidas, mas pelo menos a escala será um pouco diferente em cada uma Se não, então podemos estar aleatoriamente entre a ilha grande e a pequena E, novamente, eles ainda terão uma boa escala aleatória aplicada. E, finalmente, todos eles ainda terão a mesma aparência. Assim, podemos pegar nossos detalhes de rotação e também podemos randomizá-los Então, vamos extrair da malha estática e eu vou encontrar a rotação ativa definida. Neste caso, só queremos girar em torno do eixo z porque, lembre-se, isso vai ser para cima ou para baixo no mundo Então, vamos clicar com o botão direito do mouse e dividir a estrutura. Na verdade, vou ser um pouco preguiçoso e pegar o flutuador aleatório ao alcance Duplique isso aqui, vamos apenas girar de 0 a 360 graus Então, essa é uma daquelas vezes em que não acho que haja valor em realmente promover isso para uma variável. Acho que está bem claro. Quando olhamos para algo, estamos definindo a rotação dos atores e vamos de 0 a 360, então, obviamente, estamos permitindo uma rotação completa Então, na verdade, eu não recomendaria promover isso para uma variável. Algumas coisas podem funcionar como um número mágico, especialmente porque sabemos que não vamos atualizar ou ajustar isso Não há razão para eu ver que vamos querer vincular isso a uma coisa diferente Promover isso para uma variável significa que não precisamos voltar ao código. E se quiséssemos mudar completamente a escala sem encontrar o código em si, poderíamos definir isso para 0,4 ou 2,5 ou o que quiséssemos para realmente exagerar a escala. Eu não vou fazer isso. Vou manter isso como 0,8 e 1,2. Então, apenas essas três mudanças, teremos algo que agora parece muito mais aleatório e um pouco mais exclusivo do que apenas ter os mesmos dois objetos aparecendo exatamente na mesma escala e rotação quando são colocados em jogo Agora podemos passar para o movimento. É por isso que mantivemos o evento. Novamente, queremos um movimento agradável, consistente e suave e, com uma lógica muito simples, não vai ficar muito caro de executar. Vamos retirar o pino de execução e encontrar a diferença mundial do ator publicitário Queremos esse aqui? Adicione o deslocamento mundial do ator para todo o ator da ilha Dê a nós mesmos algum espaço porque precisamos fazer alguns cálculos aqui para o deslocamento Criaremos uma nova variável. Vou promover os Delta Seconds novamente só para ser preguiçoso aqui Transforme isso em variável para obtermos o tipo correto, e eu chamarei isso de velocidade de movimento. Clique em Compilar e definimos isso padrão de algo como 400 unidades de velocidade, mas vamos querer ter certeza de dar a isso um valor negativo, ou seja, 400 negativos para garantir que isso esteja rolando para baixo na Podemos nos livrar da nossa velocidade de movimento. Só queremos multiplicar nossa velocidade de movimento por segundos Delta. E vamos inserir isso em nosso valor aqui. Acabei de perceber olhando para isso. Não queremos adicionar um deslocamento mundial aqui, então vamos excluí-lo Na verdade, queremos adicionar o deslocamento local. Então, usaremos o deslocamento local do ator de adição. Divida a estrutura p para o Delta e, em seguida, conectaremos isso à nossa localização no Delta X porque, novamente, estamos apenas movendo isso no X para frente na tela Não precisamos calcular com nenhuma física ou algo parecido, tentar criar qualquer pseudofísica ao longo do tempo Portanto, não estamos usando a compensação mundial. Podemos usar o deslocamento local. Vou ver onde o ator está atualmente, e isso apenas adicionará esse valor à direção X. Na verdade, o motivo que me veio à mente é que, se voltarmos ao tutorial de tiro, acessaremos nossos projéteis e abriremos uma classe de projéteis Podemos ver o evento aqui. Na verdade, essa é a mesma lógica que estamos usando para mover nossos projéteis A ilha é essencialmente um projétil muito lento e muito grande na forma como temos nosso código Novamente, isso é na verdade algo que está usando o mesmo código. Lembre-se de que estamos fazendo um pouco de duplicação novamente, e isso pode ser em um projeto maior, em você começa a analisar coisas como composição, onde poderíamos ter um componente de movimento personalizado, que, por ser muito semelhante e tudo o que realmente precisamos é de uma direção ou velocidade, podemos ter esses valores expostos em um componente personalizado e poderíamos distribuí-las aos diferentes atores que precisam delas. Como mencionei, um pouco fora do escopo do conteúdo que estamos analisando no momento, mas apenas algo a considerar. Isso não é o fim do mundo, então vamos manter isso como está. E agora podemos realmente começar a gerá-los. Então é aqui que a classe simples de ator genérico, a classe geradora que criamos se tornará bastante útil Então, se entrarmos em nosso nível, primeiro, eu só quero testar rapidamente a aparência das ilhas , então vou pegar uma das ilhas e jogá-la no hidroavião na parte inferior. Queremos ter uma ideia aproximada da altura em que queremos gerar isso Novamente, isso se resumirá a alguns ajustes. Vou fazer um pouco disso agora, mas provavelmente vou refinar isso fora Então eu acho que, na verdade, a primeira vez que eu deixei cair um desses, foi, na verdade, o mesmo que o avião em si, então -4.000 Então, podemos usar isso como base. Provavelmente colocaremos o gerador no mesmo local. Queremos ter certeza de que isso está mais longe da câmera. Então, isso é algo que agora podemos testar facilmente. Vamos pegar nosso ator de câmera. Vamos fixar isso aqui e podemos começar a realmente ajustar e garantir que tudo apareça fora da tela Então, para a ilha grande aqui, além de talvez alguma contabilização de que possamos até uma escala de 1,2, lembre-se, é nossa escala aleatória Então, se obtivermos o maior spondm da ilha, precisamos que ele esteja pelo menos no ponto de 11.360 no X para ficar completamente fora de vista quando houver Então, esse é o nosso ponto essencial em que queremos que nosso gerador de ilhas seja colocado Então, na verdade, vou pegar isso aqui, virar aquele zero no y, então vamos começar pelo meio. O que vou fazer é, com o selecionado, voltar para a pasta do blueprint aqui Eu vou para a pasta de spawners. Selecione isso. E com isso selecionado no sorteio de conteúdo, só uma dica útil que você está prestes a ver aqui Podemos clicar com o botão direito do mouse nesta ilha. Vamos substituir o Actor e podemos substituí-lo pelo que selecionamos atualmente em nossa gaveta de conteúdo Então, vamos renomear isso. Este objeto, podemos ver, agora é uma chave de sublinhado da BP Vou renomear este para Island spawner. Então está claro o que isso está fazendo. E, de fato, quando se trata de nomenclatura, isso vai começar a ficar um pouco descuidado à medida que nós O que eu realmente deveria ter feito é chamar essa ilha de sublinhado do gerador porque podemos ver que isso Então, também podemos renomear este para gerar sublinhado inimigo. Então, agora está um pouco claro que esse é o nosso gerador inimigo. Este é o nosso criador de ilhas, e eles serão agrupados Agora, outra coisa que podemos ver como um problema é que a malha estática tem o tamanho errado. Acho que talvez estivesse considerando um ativo diferente com o qual estava trabalhando antes. Então, nós só queremos talvez aumentar isso para algo como 120 em todos os eixos, talvez até 160. Perfeitamente bem. O principal é cobrir toda a câmera. Então, podemos ver agora, no modo de jogo, que temos a água cobrindo tudo. O gerador estará do lado de fora da câmera para possamos garantir que as ilhas apareçam fora da Agora, uma coisa muito importante que eu estava prestes a perder completamente é que, se voltarmos para a ilha geradora, quando eu estava ajustando isso, ajustei a escala Agora, sempre queremos ter certeza de mantê-los uniformes, porque em alguns códigos de desova, você pode considerar a rotação da localização do ator em escala como o ponto no qual a geração será escala como o ponto no qual a Portanto, não queremos adicionar nenhum padrão, como um deslocamento predefinido, à escala de nada, então certifique-se de transformá-lo Então, para fazer isso funcionar para a desova da ilha, vamos querer inserir isso e selecionar nossa classe de ilha Então, queremos a ilha de sublinhados da BP. Vamos permitir um deslocamento aleatório, então vamos marcar isso. Forneceremos uma distância de deslocamento de, digamos, 5.000 unidades em cada lado Portanto, lembre-se de que isso é apenas usar a funcionalidade integrada que já implementamos quando planejávamos um pouco com antecedência ao criar nossa classe geradora genérica E nos intervalos de desova, não queremos muitas ilhas bagunçando Então, vamos definir isso para algo como 5 segundos e a cada 10 segundos. Então, de 5 a 10 segundos, devemos comprar uma nova ilha. Acabei de recapitular rapidamente o motivo pelo qual estamos usando o deslocamento aqui. Lembre-se de que criamos em nossa base de geradores, iniciamos nossa ramificação no spawn iniciamos nossa ramificação ou uma verificação booleana aqui, desculpe, para saber se devemos permitir algum deslocamento aleatório Se dissermos não, então simplesmente geraríamos a ilha exatamente no ponto do gerador, o que significa que temos apenas uma linha reta de ilha constante, o que, novamente, seria um pouco estranho Se dissermos que sim, ele escolherá um flutuador aleatório dentro de um intervalo, o que, no nosso caso, porque definimos isso como 5.000, o que seria entre 5.000 em Y e menos 5.000 em Y. Então, isso deve nos dar muita variação em seu ponto inicial, sua escala, sua rotação e até mesmo na malha Então, podemos testar isso agora, se pressionarmos , veremos em algum lugar dentro de 5 segundos. Vou me livrar da câmera muito rapidamente. No modo de jogo, podemos testar isso e esperar um pouco, e veremos as ilhas começarem a aparecer. Estamos procurando coisas como garantir elas não estejam simplesmente surgindo, garantir que estejam indo na direção correta, o que acho que podemos ter problemas aqui, e também que elas estejam surgindo corretamente dentro do deslocamento que fornecemos que elas não estejam simplesmente surgindo, garantir que estejam indo na direção correta, o que acho que podemos ter problemas aqui, e também que elas estejam surgindo corretamente dentro do deslocamento que fornecemos. Então eu não estou vendo nada. Há uma ilha muito pequena. Isso pode ter levado 10 segundos, mas temos uma ilha muito pequena surgindo do fundo É meio cômico, mas acho que ainda parece muito bom E devemos ver, esperançosamente, mais algumas ilhas chegando nos próximos segundos. Ok, então, na verdade, temos muitas ilhas. Um problema temos é que, com sua rotação aleatória, elas estão avançando com base na direção em que foram geradas Então, vamos em frente. Acho que talvez eu tenha estragado um pouco da lógica quando criamos a lógica do movimento E eu acho que, na verdade, está voltando ao que estávamos vendo anteriormente. Então, na classe da ilha, acho que era isso aqui, a compensação local versus a compensação mundial que eu tinha em mente Portanto, seria bom se pudéssemos manter o código, semelhante ao projétil, e provavelmente pudéssemos alterar o código do projétil Mas acho que o que estamos fazendo, apenas para manter isso simples e simples, vamos mudar isso de nosso deslocamento local, porque lembre-se, quando estamos fazendo uma adição local ou um deslocamento para a posição local do ator, isso levará em consideração a rotação atual que ele tem, porque queremos girar ou se estamos girando 180 graus para o outro a direção e, em seguida, o avanço local mudou, então vamos nos mover na outra direção. Dizer isso, porém, me fez perceber que provavelmente poderíamos fazer algo um pouco mais limpo aqui, focando na hierarquia Então, novamente, isso é algo em que no pré-desenvolvimento, eu simplesmente esqueci isso E esse sou eu, pensando meio que na hora, é por isso que estou mantendo isso apenas para mostrar maneiras resolver problemas diferentes de várias maneiras. Então, o que eu estou tentado a fazer é porque eu quero manter essa lógica Eu quero fazer o movimento local de compensação. O que eu acho que faremos em vez disso é adicionar um novo componente. Vamos criar um componente de cena vazio e fazer disso a nova rota. Então, o componente da cena será a forma como estamos encarando, que sempre será avançada no mundo. E acho que o que faremos em vez disso é definir nossa rotação, mas não vamos definir a rotação de todo o ator. Vamos deixar o componente da cena sempre voltado para frente. E isso também lhe dará um bom exemplo de maneiras diferentes de usar a hierarquia Podemos pegar nossa partida estática e, em vez disso, vamos definir a rotação dela. Isso também é algo que ainda não vimos, então podemos definir a rotação relativa de nossos componentes em relação ao componente pai ao qual eles estão conectados. Mas exatamente a mesma lógica. Vamos conectar isso. pegar esse flutuador aleatório que já temos e dividir o pino da estrutura como fizemos antes Em vez disso, vamos apenas conectar isso ao Z aqui. Isso significa que podemos manter nossa lógica de movimento exatamente a mesma. E agora não estamos mudando a rotação de todo o ator e a forma como ele está voltado. Isso ainda está voltado para a mesma direção. Estamos apenas alterando a rotação do elemento visual. Mais ou menos como separamos isso dos aviões, onde o elemento visual é apenas o corpo do avião, mas a colisão real e tudo está apoiado nessa colideosfera Então, se voltarmos e jogarmos, veremos que isso está funcionando agora. Outro comando útil do console aqui é que podemos pressionar a tecla Tilda, digitar slow mo e definir quantas vezes mais rápido queremos que seja Então, se configurarmos isso como slow mo five, você pode ver que isso está se movendo cinco vezes mais rápido, muito mais fácil de testar e realmente ver se as ilhas estão surgindo corretamente Então, agora eles estão se movendo para baixo na tela. Parece que está funcionando corretamente. Lembramos aquele teste em que não vamos continuar gerando Se o jogador estiver morto. Comando novamente o console, podemos digitar um nível de reinicialização, voltar direto para o Slom five e fazer alguns testes apenas para garantir que as ilhas, apenas garantindo que façamos as ilhas, apenas garantindo vários testes em qualquer lugar, que as ilhas estejam funcionando bem Então, eles estão se agrupando muito, mas quero dizer, novamente, é aqui que entra a randomização Talvez isso aconteça, mas está fornecendo bom tipo de variação, e acho que parece muito bom. Talvez queira adicionar um pouco mais de atraso entre as ilhas iniciais, mas acho que só para esse tipo de projeto, isso parece muito legal e ter alguma sobreposição só dá uma variedade extra Outra coisa que você pode querer fazer é entrar na classe base do gerador. Se entrarmos aqui, geraremos imediatamente o Actor Se entrarmos aqui, geraremos imediatamente o Actor geraremos imediatamente Então, devemos ter um. Se apenas clicarmos em simulações. Devemos apenas verificar novamente. Sim, recebemos um imediatamente, o que é perfeitamente normal. Eu estava pensando que talvez já tivéssemos tido um atraso inicial, mas acho que a única razão pela qual não vemos por um tempo é porque demora um pouco para aparecer na tela. Então, na verdade, nascemos em uma ilha imediatamente. Mas estou meio que me perguntando onde isso está agora. Então, é só demorar especialmente se gerar uma pequena, antes de tudo Vai demorar um pouco mais para vê-lo antes de entrar em cena. Não é o fim do mundo. Novamente, randomização, você terá alguns resultados diferentes lá Mesmo com a ilha maior, acho que está demorando um pouco para aparecer na tela. Então, talvez o que eu fique tentado a fazer e, novamente, isso se resuma a muitas viagens agora brincando Talvez estivéssemos um pouco preocupados com a distância desta manhã. Então, vamos trazer isso de volta um pouco e, novamente, garantir que toda vez que você pressionar a placa, olho para garantir que nada apareça, mas queremos que essa ilha talvez apareça na tela um pouco mais cedo Então, como mencionei, tentativa e erro, veja como as coisas correm, fique de olho nos resultados que você está obtendo e certifique-se de que o jogo esteja funcionando bem à medida que você avança. Então eu acho que isso é muito legal lá. deveriam começar a ficar um No entanto, é aqui que as coisas deveriam começar a ficar um pouco mais interessantes. Agora você tem controle total sobre o design dos níveis, onde queria que as coisas surgissem, a velocidade com que queria que elas se movessem, na verdade, apenas refinando a jogabilidade e a aparência do jogo que você tem Se as coisas estiverem surgindo, você pode simplesmente mover o gerador um pouco mais para trás Se você quiser que eles apareçam mais cedo , podemos aproximá-los um pouco mais. Se a água não estiver cobrindo toda a visão, basta aumentar o plano como você acabou de ver. E se as ilhas estiverem muito próximas, basta diminuir a velocidade de desova e coisas assim E isso é pura iteração, jogar, observar, ajustar, repetir É raro que você consiga essa primeira vez perfeita. Você acabou de me ver precisando ajustar e mudar algumas coisas até mesmo para esta demonstração aqui, mas deve ser aí que entra parte da diversão de criar jogos, porque é aqui que agora você tem muito mais controle sobre como refinar o resultado final Agora, uma coisa que eu diria é que neste momento também valerá a pena ficar olho no esboço, como mencionei Temos algumas coisas, mas nossos volumes de bloqueio estão perfeitamente corretos. Talvez colocando coisas em pastas como a iluminação que veio por padrão. Uma coisa que eu percebi que não estamos realmente usando é a esfera do céu ao fundo. Esse é um objeto antigo. Não está fazendo nada. Podemos nos livrar da esfera do céu. Você pode ver que nada muda, apenas para garantir que não tenhamos mais objetos no nível do que precisamos. Todo o resto está bem. Isso está fornecendo a luz e a atmosfera em segundo plano. Mas fique à vontade para começar a brincar com elas, mudando a direção da luz direcional, a força dela para fazer com que as coisas pareçam mais claras Novamente, comece a ser criativo e a jogar com as diferentes propriedades e detalhes para fazer com que o jogo tenha a aparência que você pretendia. Então, isso é tudo para o nosso nível. As coisas agora parecem um pouco mais vivas. Temos ilhas de água, com as quais você pode jogar paralaxe. Na verdade, está começando a parecer um pequeno jogo. Em seguida, podemos começar a usar o passe polido, fazendo com que as coisas pareçam realmente interessantes e muito mais atraentes visualmente para o jogador 24. 23 — NiagaraParticles: Ponto em que podemos começar a melhorar a sensação geral e apelo de alguém que joga nosso jogo. Vamos começar com uma série sofisticada de efeitos, adicionando coisas como propulsores, explosão e impacto, tudo usando o motor Unreal embutido Então, uma rápida visão geral dos sistemas e emissores que veremos em nosso projeto Se navegarmos até nosso projeto, acessarmos a pasta Assets and effects, teremos nossos sistemas Niagara aqui Mas basta abrir um desses. Por enquanto, usaremos o mecanismo de pixels apenas para mostrar com o que estamos trabalhando. Então, o que estamos dentro no momento é um sistema de Niágara Os sistemas geralmente são compostos por um e, muitas vezes, mais de um emissor. Podemos ver aqui que os painéis com abas laranja são nossos emissores que compõem os diferentes pontos do nosso sistema geral Isso torna o Niagara muito mais flexível para trabalhar do que o antigo sistema de partículas em cascata É muito mais fácil criar alguns emissores básicos no novo sistema e, em seguida, podemos começar a juntá-los para criar sistemas personalizados e exclusivos De uma forma muito simplista, você pode pensar nisso como algo como um sistema de partículas de chama Você pode ter muitos emissores que entrariam nisso. Você teria as faíscas vindo do topo da chama. Você teria um pouco de fumaça. Você poderia ter o efeito de distorção e teria o corpo principal da chama e o próprio fogo Todos esses podem ser emissores individuais construindo esse grande sistema O importante é ter em mente que os emissores devem ser reutilizáveis Não os colocamos diretamente em nossos projetos ou nos sistemas que usaremos e realmente usaremos dentro do nosso código ou do próprio nível Se você quiser começar a experimentar alguns dos sistemas que eu já forneci, você pode ver que tenho vários aqui. Você pode facilmente entrar e começar a brincar com as propriedades dos emissores Se você quiser ver qual parte é responsável por um determinado efeito acontecendo aqui no pote de visualização, podemos desmarcá-las aqui Podemos ver que isso é apenas uma fonte de luz, então nada realmente muda. Se ligarmos isso novamente, mas depois desligarmos o outro emissor, podemos ver que ele é claramente o responsável pelo efeito de partículas do corpo do nosso motor Então, se você quiser começar a tentar brincar com coisas como a cor, o tamanho disso, talvez não saiba exatamente o que está procurando imediatamente, o que é Mas só de dar uma olhada rápida nas propriedades fornecidas, podemos ver que provavelmente poderíamos alterar a cor de nossos valores de escala aqui Isso está deixando a cor amarela laranja aqui. Se dermos mais azul, obteremos uma cor diferente ao longo da vida útil da partícula É outra ótima maneira de se acostumar com alguns dos sistemas do Unreal, apenas encontrando as coisas que instintivamente fazem sentido para você e brincando e enfraquecendo os valores que você pode Você também pode adicionar coisas diferentes, como velocidade extra, para fazer essa viagem ainda mais longe E, como mencionei antes, uma ótima maneira de descobrir por que as coisas são responsáveis é adicionar um valor muito grande a isso, para que possamos ver que, se fizermos a velocidade aqui 11.000 em vez de 1.000, podemos ver exatamente pelo que isso foi responsável, e então podemos refinar e ajustar até um valor com o qual achamos que talvez queiramos trabalhar Então, como em alguns dos outros sistemas do projeto que analisamos até agora, o lado mais artístico das coisas realmente não é o foco do que estamos tentando abordar nesses tópicos. Então, eu não vou me aprofundar no Niágara. Quero mostrar como usá-lo e como podemos implementá-lo em um projeto. Útil se você tiver coisas como acesso a Asset PACs ou alguns exemplos gratuitos de coisas como o projeto de exemplo de conteúdo fornecido pela Epic A primeira coisa, como já estamos nessa partícula, podemos usá-la para o propulsor de ambas as classes de aviões Ambos precisarão disso, tanto o inimigo quanto o jogador. Então, se formos para nossa aula de blueprint, iremos para CR e encontraremos sublinhado da BP Então, podemos colocar isso na classe base novamente, e isso será usado para nossos dois planos diferentes. Precisamos ter muito cuidado novamente onde vamos colocar isso. Poderíamos colocá-lo diretamente na esfera, mas acho que, no momento, caso quiséssemos fazer alguma rotação de deslocamento específica, coisas assim na malha estática, vamos colocá-lo aqui Então, vamos pegar a malha estática. Vamos adicionar um novo componente e queremos pesquisar o Niágara Podemos ver aqui que temos apenas uma opção, o componente do partículas do Niágara E no painel de detalhes, veremos a lista suspensa que provavelmente estamos procurando e com a qual já estamos bastante familiarizados. Podemos soltar isso e selecionar o mecanismo de pixels. Se navegarmos até o visor, podemos ver que ele está meio que encaixado no meio do Amopla, então precisaremos recuar um pouco recuar um E acho que vou colocar isso mais ou menos perto do círculo de metal que adicionei no plano aqui. Se clicarmos em Compilar de forma segura, talvez precisemos testar algumas coisas com isso Então, a primeira é a rotação diferente que vamos aplicar às diferentes classes infantis. Então, se começarmos dentro do player simples e apenas verificarmos o ponto de vista aqui, este parece perfeitamente bom Essa é essencialmente a mesma configuração da base do avião. Se entrarmos em um inimigo simples, vá até o visor aqui, para que possamos ver que o efeito de partícula está bom aqui No entanto, se pressionarmos play, então se entrarmos em nosso visor e no modo de jogo aqui, podemos ver que está tudo bem para o jogador, mas as partículas do inimigo estão um pouco estranhas, porque lembre-se de que, quando entramos no modo de jogo, estamos invertendo completamente a rotação nosso inimigo com base na localização dos E mesmo que esse efeito de partícula esteja aninhado, se observarmos a configuração no mecanismo P underscore pixel, podemos ver que a velocidade está definida uma direção específica Então, o que queremos fazer, e isso será apenas um ajuste muito simples em um sistema de partículas existente Para que você possa começar a trabalhar pelo menos um pouco, precisamos fazer uma cópia do mecanismo de pixels Então, vamos voltar aos nossos efeitos. Vamos para nossos sistemas de Niágara. Temos nosso motor de pixels aqui. Outra coisa, eles foram copiados dos exemplos de conteúdo que não têm a melhor nomenclatura, então vamos pegar isso e renomeá-lo para renomeá-lo Portanto, a convenção de nomenclatura adequada seria sistema Nagra, motor de sublinhado de pixels, e chamaremos isso Então, podemos deixar este exatamente como está. Podemos então pressionar Control, na verdade, para duplicar isso, e chamaremos isso de inimigo sublinhado E se clicarmos duas vezes para abrir a versão inimiga, o que queremos fazer é encontrar nossa velocidade Já vimos que isso controla a direção em que o efeito da partícula está indo, e vamos apenas remover a opção de negação Também podemos fazer algo enquanto estamos aqui, tornando este talvez um pouco mais verde para que possamos arrastar o valor até aqui para dar a ele uma tonalidade um pouco diferente E se considerarmos isso além do valor vermelho, podemos ver que é um pouco mais de um propulsor verde aqui, apenas para torná-lo um pouco mais exclusivo para a versão inimiga em que vamos colocá-lo Então, podemos clicar em compilar e economizar nisso. Vamos voltar para a classe inimiga. Vamos pegar nosso sistema de partículas do Niágara aqui, e tudo o que queremos fazer é mudar isso do jogador, que acabamos de renomear e mudar para a versão inimiga Então, isso vai parecer quebrado na planta. Tudo bem, porque assim que entramos no playode, isso leva em consideração a direção mundial do movimento do sistema de partículas, e não a entidade que Então, podemos ver que agora está funcionando perfeitamente bem. Um pouco diferente porque temos cores diferentes, então também parece um pouco mais interessante. Um bom ajuste simples só para colocar um pouco de mãos no sistema de partículas existente, e temos o sistema do jogador e do inimigo funcionando Então, essa é uma forma de aplicarmos partículas sem código diretamente em componentes e recursos existentes. Agora, se você se lembra, também temos algumas coisas prontas para começar a ser implementadas em nosso código. Lembre-se de algumas delas para fazer comentários. Então, um dos que eu me lembro de ter estava na verdade em nossa classe de plantas para nossos projéteis Então, se entrarmos na base de projéteis de sublinhado da BP, e exatamente o que eu mencionei anteriormente, vou digitar todo Encontraremos aquele comentário que eu mesmo deixei , e está aqui embaixo. Então, se você não deixou esse comentário, basta navegar até a sobreposição de início do componente, e é aqui que queremos colocar alguns efeitos E vamos começar com nosso sistema de partículas simples para mostrar que duas coisas tiveram impacto Então, entre aplicar dano e, novamente, o que é muito importante antes de destruirmos o projétil, vamos puxar o pino de execução e procurar algo chamado sistema de desova no local Então, queremos essa opção aqui, abranger o sistema no local. Agora, há algumas coisas diferentes se você mesmo começar a examinar mais as partículas para aproveitar o que estamos fazendo aqui. Você também pode se deparar com o termo emissor de spawn. Então, se pesquisarmos o emissor Born no local, é uma terminologia muito semelhante, e essa é essencialmente a versão antiga do sistema de partículas Portanto, ainda não foi totalmente removido, mas eu o mencionei brevemente há pouco. Costumava haver algo chamado sistema de partículas em cascata Não era tão flexível, não tinha tantos recursos. Não é tão fácil programar, mas agora usamos o sistema Niagara Portanto, quando você quiser trabalhar com o Niágara, que é o ideal em que você se concentrará, procure algo chamado sistema de palavras que surja bastante Ao trabalhar com cascata, se estiver em um projeto antigo ou antigo, talvez você veja a palavra emissor aparecer Então, os artigos em cascata eram chamados de emissores, enquanto agora, como mencionei, um emissor é apenas um único elemento que constrói um sistema inteiro que constrói um Então essa é a maneira mais fácil de se lembrar disso. Então, estamos procurando um sistema. Você sabe que também tem o correto , porque se colocarmos isso abaixo, não temos nada válido para colocar no slot do emissor. Então, vamos nos livrar disso. Se derrubarmos este, queremos encontrar nosso impacto metálico. Então é isso que queremos usar quando dois projéteis ou um projétil atingem outra superfície Então esse é o emissor que queremos gerar. E isso nos permite trazê-los em tempo de execução, fazendo com que os projetos pareçam um pouco mais dinâmicos. A localização será muito simples. Vamos partir daqui e vamos procurar a localização do ator. Então, é aqui que queremos que o efeito de partícula apareça, o ponto de impacto, essencialmente, de onde duas coisas acontecem A rotação em escala deixaremos como padrão. Não precisamos alterá-los. Voltaremos e faremos alguns efeitos sonoros e outras coisas mais tarde. Então, na verdade, vou deixar esse comentário para mim mais tarde, pois precisarei voltar e adicionar mais algumas coisas. Mas, novamente, agora podemos entrar e testar, e o que devemos ver é que toda vez um projétil atinge algo, teremos algum tipo de efeito de partícula sendo Então, é um pouco extremo, mas podemos definitivamente ver que isso está acontecendo. E, novamente, você pode entrar, refinar as diferentes escalas e coisas assim Mas agora recebemos alguns comentários de que duas coisas colidiram, que faz com que o jogo pareça muito mais interessante e intuitivo de jogar Eu também forneci, além do impacto metálico. Você também pode usar a explosão de pixels, então depende totalmente de você. Eu acho que eles parecem um pouco diferentes. Basta verificar sua aparência. Esse pode ser um pouco mais adequado na verdade, para o impacto menor Então, vou manter isso com a explosão de pixels. Mas essa é a principal coisa que temos agora: esse feedback visual. E então queremos fazer a mesma coisa nossos dois aviões. Então, novamente, mostramos isso na classe base, então vamos para a base do plano de sublinhado da BP Acho que também me deixei aqui, e vamos clicar duas vezes nisso. Então, para implementar efeitos de morte de avião. Então, esses serão os efeitos que eu quero reproduzir quando qualquer um dos aviões for destruído. Então, a mesma coisa novamente. Nós vamos sair daqui. Vamos procurar a opção do sistema Born. Pegue o sistema de extensão no local. Mesma propriedade. Então, onde quer que o avião tenha acabado de ser destruído, esse será o local. Então, vamos encontrar a localização do ato. E vamos fazer isso de uma maneira um pouco diferente aqui. Então, como fizemos no passado, queremos tornar isso flexível porque estamos expondo isso para uso nas classes secundárias do pai, onde está a lógica central Então, vamos pegar nosso modelo de sistema aqui e vamos apenas promovê-lo para uma variável. Estamos renomeando este para efeito de partícula de explosão. E precisaremos mudar isso nas classes infantis porque o jogador e o inimigo têm efeitos de partículas ligeiramente diferentes Então, clicamos em compilar e salvar. Vamos entrar na classe avião, a classe avião do jogador. Certifique-se de que selecionamos o elemento superior, e devemos ser capazes de ver em algum lugar aqui embaixo, agora temos um efeito de partícula de explosão A partir deste, vou encontrar o Pixel Explosion Player e, em seguida, clicaremos em compilar, exceto entrar no avião inimigo O mesmo de novo. Pegue o elemento superior. Vamos encontrar nossa partícula de explosão e mudá-la para a versão inimiga Tão bonito e simples, compile e salve novamente. E agora queremos testar e ver como isso funciona quando as coisas realmente se chocam. Então, vemos que há um pequeno atraso na primeira vez que chega Em um jogo totalmente leve, você vai querer executar algo para que os shaders sejam pré-compilados, para garantir que todos os efeitos sejam essencialmente redondos , pelo menos um, para que não tenhamos esse atraso Mas agora que superamos isso, podemos ver que temos os diferentes efeitos. E também podemos testar. Quando o jogador morre, recebemos a mesma coisa. Portanto, é um pouco diferente se verificarmos e olharmos para eles. Acho que um é um pouco mais azul, então temos uma espécie de explosão azul aqui, e o outro tem aquela tonalidade verde Portanto, talvez você queira entrar e alterar as propriedades da cor. E você pode ver que, à medida que as coisas ficam um pouco mais complexas, podemos ver a complexidade, o número de emissores que está aumentando Mas quando você começa a se familiarizar com as coisas que está procurando, elas são relativamente fáceis de ajustar alterar e configurar para funcionar exatamente como você deseja Esse é o lado da programação. Isso é realmente tudo o que precisamos fazer para que alguns efeitos de partículas sejam reproduzidos. Portanto, é uma etapa relativamente simples adicionar um bom polimento ao nosso projeto. E essa é outra daquelas coisas em que experimentar e brincar com as coisas realmente vão beneficiar você mais do que qualquer outra coisa. Por exemplo, tirei os efeitos das partículas diretamente dos exemplos de conteúdo épico e acho que, apenas para a configuração geral as explosões parecem um pouco finas demais, não tão grossas quanto eu gostaria Então, o que eu poderia ficar tentado a fazer em ambos seria entrar e encontrar as coisas especificamente relacionadas à escala da malha Então, essas são três dessas medidas estáticas. Eu posso ver aqui que temos um tamanho de malha de escala, e eu poderia simplesmente aumentá-lo para algo muito maior por padrão. Eu posso ver aqui exatamente qual elemento está tendo efeito, para que possamos ver quais acabaram de ficar muito maiores. Eu fiz isso quatro vezes maior do que era. Agora, novamente, isso consome um pouco de tempo porque preciso fazer isso para cada um dos diferentes elementos. Então, eu entraria neste, por exemplo, definiria isso para quatro, quatro e quatro. Mas agora temos imediatamente um tipo muito maior de explosão robusta para o tipo de estrela que estamos procurando Então, mudanças realmente simples como essa podem realmente fazer a diferença nos emissores e tudo que eu tive que fazer foi entrar e encontrar o tamanho da malha Então, se eu quisesse testar isso em nosso inimigo, faria a mesma coisa novamente, para que pudéssemos pegar a escala de malha definir isso para quatro, quatro e quatro, para que corresponda ao jogador. E estamos fazendo isso apenas para cada um dos diferentes emissores, para que tudo permaneça um pouco uniforme , porque eles representam elementos diferentes do sistema de explosão Então, compile e salve isso, podemos entrar e jogar e ver como fica R: Acho que é muito melhor. Acho que mostra uma boa diferença entre o impacto geral do projétil em comparação com a explosão dos navios. Então, coisas muito pequenas como essas. Você também pode encontrar as cores, especialmente se tiver inimigos de cores diferentes dos que eu escolhi. Você pode entrar na explosão inimiga, encontrar todas as propriedades de cor entre todos os diferentes emissores, ver quais são responsáveis por qual cor e depois alterá-las de acordo com sua preferência Lembre-se de que uma dica rápida é que, se você não tiver certeza de qual elemento deseja alterar, podemos simplesmente desmarcar os diferentes emissores aqui e ver o que é responsável por qual parte. Então você pode passar. Isso seria apenas aquele tipo de após o fumo, então podemos desligá-lo. O do meio é para a cor principal. Então, se meus inimigos são, na verdade, verdes. Então, talvez fizesse mais sentido ter uma cor mais verde, para que possamos valorizar o verde e aumentar isso até o fim. E depois vamos. Temos mais uma explosão verde para a noite inimiga. Então, temos um bom tipo de amarelo começando com uma explosão aquecida. Mas então estamos mostrando que isso na verdade está voltando para uma prorrogação verde, que é a cor da carroceria da nave inimiga Então, novamente, uma mudança muito, muito rápida. Desde que você saiba mais ou menos o que está procurando, podemos fazer essas alterações rapidamente. E veja isso meio que se encaixar muito bem. Então, brinque com esses tipos de coisas. Esses são tipos de abordagens que farão com que você entenda os sistemas muito mais rapidamente. Você não necessariamente saberá exatamente o que está procurando ao começar, mas acho que, especialmente com algo como o sistema Niagara, as convenções de nomenclatura, as coisas que você está procurando e o feedback imediato que você recebe do ponto de vista, é uma maneira muito útil de aprender isso rapidamente, apenas por meio de alguns erros de tentativa Então, essa é a primeira etapa para melhorar nosso feedback visual. Isso faz com que tudo pareça vivo. Os inimigos ainda estão meio que surgindo do nada. Em seguida, no próximo tópico, queremos adicionar aquelas animações de desova muito boas que foram fornecidas no 25. 24 — Efeitos de áudio: ter dito que vamos entrar no Festival de Animação, mas percebo que, na verdade, estamos ignorando a peça que faltava aqui. E isso geralmente é algo que é deixado tarde demais no desenvolvimento de jogos, que é o áudio. Queremos começar a analisar o uso de San cues para randomizar uma quantidade mínima de arquivos de áudio para fazer que as coisas pareçam um pouco mais variadas e interessantes Também é uma dessas coisas que, se você está protótipo de seu próprio jogo, é muito, muito fácil ignorar e subestimar a importância do áudio Você pode achar que seu jogo parece monótono ou chato. Você pode adicionar coisas como efeitos de partículas, trepidação da câmera e todas essas outras coisas, e pode ser que falte algum áudio no projeto que realmente ajudaria a dar vida a ele Então, vamos nos concentrar neste festival. Então, se entrarmos em nosso sorteio de conteúdo, vamos para a pasta de áudio. Eu forneci alguns arquivos de som diferentes. Temos um para a explosão, então vamos usá-los para nossos aviões quando eles explodirem, e temos o efeito de tiro, que será reproduzido sempre que estivermos atirando para nossos aviões quando eles explodirem, e temos o efeito de tiro, que será reproduzido sempre que estivermos atirando que será reproduzido sempre que estivermos Provavelmente não vamos usar isso para o inimigo, mas, novamente, você pode ajustar e contornar as coisas para ver como gostaria que o projeto fosse configurado Acho que se houver muitas coisas disparando ao mesmo tempo, isso pode facilmente se tornar uma sobrecarga auditiva Se você quiser testar os arquivos de áudio e ver como eles soam, podemos pular o botão de reprodução aqui e você terá uma reprodução imediata no editor Se nos concentrarmos em nossos tiros, primeiro, já que temos dois deles, queremos selecionar os dois, clicar com o botão direito do mouse em qualquer um deles clicar com o botão direito do mouse em qualquer um e temos essa opção aqui para criar uma única fila Então, se escolhermos criar uma fila múltipla, isso criará um arquivo, um arquivo que para cada arquivo wave que temos aqui embaixo. Em vez disso, podemos pegar esses dois arquivos wave e compactá-los em uma única fila Então, clicaremos nesse . Renomeie este para SC Underscore gunshot Você pode ver que é um tipo de ativo um pouco diferente. E, basicamente, as dicas SN são uma maneira muito simples se clicarmos duas vezes para abrir Eles nos permitem trabalhar com vários arquivos de áudio sem precisar editar o arquivo de origem Assim, podemos manter o gunshot 1 e 71 exatamente como estavam quando foram importados, e podemos substituir aqui individualmente coisas como se ele deve ser repetido, o volume padrão e coisas Uma coisa a notar é que você pode ver os pregos de forma inteligente o suficiente Ele sabe que, como trouxemos mais de um arquivo assinado diferente, provavelmente queríamos randomizar a ordem em que eles são reproduzidos, que é, na verdade, o que queríamos Depois que as randomizações foram feitas, porém, queremos partir daqui e vamos procurar por algo chamado modulador Ou, na verdade, você pode ver isso aqui embaixo. Vamos conectar o resultado do nosso modulador na saída Então, isso alternará entre o som a ser reproduzido. Ele vai randomizar um desses. Vamos colocar um modulador para que possamos ajustar um pouco o áudio E então, qualquer que seja o resultado da saída, é o que será reproduzido para o usuário final. Com o modulador ainda selecionado. Você pode ver que a principal coisa que eu queria ignorar aqui é o tom mínimo e o máximo Isso só vai ajudar a garantir que embora tenhamos apenas dois arquivos de som, eles não soem exatamente iguais quando os dispararmos potencialmente centenas ou quantas vezes seguidas. Eu dou uma grande mudança de tom a ambas, então vamos definir 12,5 e a outra para 1,5 E, novamente, esses valores podem ser bastante extremos e, se o som estiver muito distorcido, é aqui que podemos voltar e começar a refiná-lo gradualmente para que soe exatamente como queremos O mesmo com o volume, podemos definir um para 0,9 e outro para 1,1. Portanto, temos uma espécie de deslocamento semelhante ao volume mínimo e máximo dos dois efeitos sonoros sempre que eles tocam Então isso foi ótimo. Pudemos ver que isso definitivamente estava funcionando exatamente como queríamos , com uma pequena ressalva Pegadinha comum com o antigo sistema Q que estamos usando aqui A randomização não é realmente tão aleatória. Você pode ver que é simplesmente alternar entre as duas opções Ele tocará A, depois B, depois A, depois B. Bastante previsível. Então, se pegarmos nossa nota aleatória, uma coisa que queremos fazer é desmarcar isso aqui, a randomização sem substituição Algo que as pessoas geralmente ignoram. Mas agora, se pressionarmos play, não precisamos necessariamente ouvi-los, então vou silenciar o volume rapidamente Mas verifique se você pode ver qual fio está sendo disparado. E o que devemos ver é que eu tive cerca de quatro ou cinco cliques lá, enquanto obtive a mesma reprodução de áudio, que está ficando muito mais próximo verdadeira randomização do que do flip-flop entre A e B. Obviamente, você também gostaria de fazer isso se tivesse várias ondas sonoras em cima disso em sua única fila Então, se você tivesse cinco ou seis, não gostaria que fosse um, dois, três, quatro, cinco, um, dois, três, 45 e assim por diante. Você gostaria que ele escolhesse aleatoriamente entre esses cinco ou seis efeitos sonoros Portanto, lembre-se sempre de entrar e desmarcar a opção randomizar sem substituição Feito isso, queremos fazer algo semelhante com as explosões. Então, vou clicar com o botão direito na onda de explosão. Vamos criar uma única fila de som para este. Vamos chamar isso de SC underscore Explosion. Obviamente, não precisaremos de nenhuma randomização entre este Temos apenas um único arquivo, mas ainda podemos usar coisas como inserir um modulador novamente no meio um modulador novamente no Então, vou conectar outro modulador aqui da mesma maneira e talvez fornecer algumas diferenças um pouco menos intensas aqui Então, talvez 0,7 a 1,3. E, novamente, podemos voltar e refinar se isso for uma mudança de tom demais Vou deixar o volume mínimo e máximo como estão. E é apenas um ajuste muito simples que vamos fazer dentro da nossa fila de som Se você estiver usando mais um plano de fundo de áudio, pode haver outras terminologias e recursos com os quais você pode brincar no lado direito e simplesmente arrastá-los para o gráfico, reproduzir até a propriedade e ajustá-los conforme achar Para esta demonstração simples, ough, vou manter isso como temos aqui. Então, vou passar rapidamente e começar a fechar algumas das janelas que eu não preciso, especialmente os efeitos de partículas, então vamos nos livrar deles E se começarmos na base de jogo, eu já estou aqui, então vou lidar com o efeito da morte primeiro. Vou deixar o comentário aqui, pois provavelmente precisaremos de mais algumas coisas um pouco mais tarde. Então, entre nosso sistema de partículas de desova e a chamada da função de destruição do ator, vou puxar o pino de execução e procurar o som reproduzido no local Então, esse é um recurso muito bom novamente dentro do Unreal. Já incorporamos o áudio espacial padrão. Assim, podemos fornecer o ponto inicial de onde queremos que esse áudio seja reproduzido. Assim, podemos tornar as coisas um pouco mais verossímeis se um avião sendo destruído na parte superior esquerda da câmera, então teremos um efeito sonoro que deve tocar um pouco mais no lado esquerdo do fone de ouvido Então, vamos usar a função padrão aqui. Vamos usar a localização do get act para descobrir onde o avião que explodiu foi destruído E então usaremos o menu suspenso de som aqui embaixo e escolheremos nosso SC, nossa dica sonora que personalizamos a explosão de sublinhado Agora, nós realmente não precisamos promover isso porque, novamente, os dois usarão os mesmos efeitos sonoros de explosão, e ambos terão sua própria randomização e coisas assim Agora, não vou usá-lo aqui, mas também queria mostrar os recursos aos quais temos acesso. Então, se usarmos o menu suspenso neste nó, se você não quiser brincar com sinais sonoros ou apenas quiser usar o arquivo de ondas de regras, ainda podemos entrar e fazer coisas como volume, multiplicação de tons Poderíamos lançar algo como uma bóia aleatória, novamente, então já vimos isso várias vezes ou idealmente, uma flutuação aleatória ao alcance, como vimos antes E isso é muito semelhante ao que configuramos na sugestão sonora para o multiplicador de tom Mas como temos uma fila de som agradável e personalizável com a qual trabalhar, vamos usá-la em vez dos arquivos de ondas sonoras padrão rurais Também podemos abordar muito mais coisas detalhadas com coisas como configurações de atenuação Então, isso é fornecer ao sistema de som de três D, uma espécie de queda, uma faixa na qual o áudio deve ficar mais alto e mais baixo, dependendo de onde é esporte Para isso, porém, vou copiar a funcionalidade que temos aqui porque queremos adicioná-la à nossa função de disparo. Então, vamos apenas mover o comentário. Vamos voltar aqui e fazer mais algumas coisas quando fizermos nossos passes finais nos efeitos, então isso ainda é relevante. Mas vamos pegar esse controle de pressão em C. Vou entrar na função de disparo. E depois que o projétil for gerado, podemos simplesmente soltá-lo aqui A mesma coisa novamente, queremos o local em que o efeito sonoro do fogo deve ser reproduzido. E vamos pegar nosso tiro aqui, e isso automaticamente reproduzirá um tiro agora, sempre que algo É porque acho que se houver quatro ou cinco inimigos na tela e todos estiverem atirando em rápida sucessão, talvez queiramos diminuir o volume deles Então, acho que o que vou fazer é, em vez de ter funções de disparo separadas em cada classe, novamente, usaremos a herança sempre que possível Vou promover o modificador de volume e vou promovê-lo para uma variável, e chamaremos isso de compensação de volume de disparo Portanto, podemos padronizar isso para um valor de um, o que já era. Então, vamos usar como padrão tocar o volume total da sugestão sonora do tiro Então, é claro, se configurarmos isso para randomizar um pouco aqui com o modulador, o volume padrão pode ser 0,9 em direção a Em seguida, substituiremos isso e multiplicaremos isso por um total de um ou pelos inimigos, por exemplo O motivo pelo qual quero usar isso é que vamos clicar em compilar e salvar Eu vou entrar na classe inimiga. Encontraremos esse valor aqui nas propriedades. Vou dar a isso um deslocamento de volume padrão de 0,5. Então, teremos o volume padrão para tiros inimigos. Portanto, mesmo que comecem a se acumular um pouco, não devem se tornar completamente insuportáveis e, como eu disse, superestimulantes Ok, então, um teste de jogo muito rápido. Descobri que os tiros provavelmente eram tão altos ou talvez mais altos do que as Então, acho que o que vou fazer é definir um volume mínimo, e isso é potencialmente baseado nos tipos de sinais que encontrei. Provavelmente foram apenas exportados, não com um bom volume normalizado Então, talvez por padrão, na verdade, vamos levar isso para 0,5 a talvez 0,7 ou talvez 0,4 a 0,7. E veremos como isso soa. Ok, então depois de alguns ajustes, descobri que um bom valor era 0,1 e 0,2 para o mínimo e um máximo para o padrão, e então vamos reduzir ainda mais o inimigo adicionando esse deslocamento de volume aqui Então isso não é o fim do mundo. Como eu disse. Os ativos são perfeitamente viáveis, mas essas são apenas coisas úteis que você pode receber ou encontrar ativos em mercados e coisas assim, e alguns podem ter sido exportados com um volume completamente diferente Portanto, é útil saber que temos vários lugares onde podemos aplicar diferentes deslocamentos de volume e coisas assim Um projeto ou um jogo de produção completo. É por isso que também é muito importante ter algo como um menu de configurações com alguns controles deslizantes de áudio realmente flexíveis para que as pessoas possam optar por tornar seus efeitos sonoros mais baixos ou mais altos do que música, a voz e coisas assim E para o amor dos ouvidos de todos, inclusive os meus, defina seu volume principal padrão para algo em torno de 50%. Ninguém gosta de ligar o jogo e ter seus tímpanos destruídos em e ter seus tímpanos destruídos 100% do volume principal quando seu jogo está um nível de volume completamente diferente qualquer outra coisa que o sistema possa estar jogando Portanto, o áudio pode realmente ser muito importante e causar uma primeira impressão muito boa ou ruim no seu jogo, dependendo de como você o usa. Mas, novamente, isso é apenas outra coisa que você vai querer ajustar e usar Ouça o que você pensa sobre os tiros em seu sistema versus a explosão Veja onde você pode querer alterar os modificadores de volume, as diferentes opções de espera que eu mostrei para tentar fazer com que seu jogo soe bem mixado e seja o mais interessante de ouvir possível, mesmo que tenhamos apenas alguns arquivos de áudio diferentes para jogar que eu mostrei para tentar fazer com que seu jogo soe bem mixado e seja o mais interessante de ouvir possível, mesmo que tenhamos apenas alguns arquivos de áudio diferentes para Você também pode acessar sites diferentes, HIO, freesound e coisas assim para baixar alguns novos efeitos sonoros e ver o que você pode adicionar ao projeto para realmente começar a torná-lo seu A principal coisa que você está procurando é jogar por alguns minutos. Alguma coisa começa a ficar irritante depois da marca dos 32 minutos E se sim, você pode simplesmente corrigir isso reduzindo o volume geral na fila de som Ou, se necessário, como eu disse, talvez queiramos até mesmo entrar e remover o tiro do inimigo , porque isso acontecerá com muita frequência Nenhuma dessas são regras claras e específicas que devemos seguir. Como acontece com muitas outras coisas, serão muitas tentativas e erros para ver o que funciona e o que melhor afeta seu resultado final. Com o feedback de áudio concluído, o jogo agora está presente, fornecendo feedback visual e auditivo Em seguida, passaremos para as animações de spawn, que são apenas um extra opcional além do brilho visual que já começamos a adicionar ao 26. 25 — SpawnAnimations: A camada final de polimento, vamos dar uma grande introdução aos nossos navios. Faremos com que o jogador e as naves inimigas deslizem e girem para a posição em vez de simplesmente surgirem Mais uma vez, uma animação na classe base que funcionará para todos os aviões com os quais queremos trabalhar. Então, por esse motivo, vamos direto para nossa gaveta de conteúdo, pasta de esquemas, núcleo e encontraremos a base do plano de sublinhado da BP Queremos voltar ao gráfico do evento principal e, ao lado do início do jogo, clicaremos com o botão direito do mouse e procuraremos um recurso útil aqui chamado Adicionar cronograma Então, é essa opção na parte inferior. Podemos dar um nome a isso. É uma espécie de função que tem seu próprio gráfico embutido. Veremos isso daqui a pouco, mas podemos dar esses nomes. Então, vamos chamar isso de anime, como em animate in. Como acontece com qualquer outra coisa, eles só serão ativados quando uma execução os atingir. Vamos extrair nosso pinhe de execução e queremos colocar isso em prática desde o início Então, essa será uma curva gráfica que podemos animar, e só queremos ter certeza de que ela sempre começa a ser reproduzida do quadro zero na curva até o final Temos outras opções, como jogar a partir de um determinado ponto, parar a animação, jogar ao contrário ou qualquer outra coisa. Só queremos jogar essencialmente do quadro zero até o final. forma como isso funciona é como uma atualização temporária, muito útil se você não precisa algo para animar constantemente Isso acionará cada quadro enquanto a linha do tempo estiver sendo reproduzida antes de chegar ao fim E então, enquanto estiver sendo acionado, ele chamará o pino de atualização aqui E então, quando terminar a animação, ele chamará o pino finalizado. Então, sabemos se e quando ele ainda está sendo reproduzido, e também sabemos quando é atingido no final da animação. Tudo isso vai ser muito útil. Então, se clicarmos duas vezes nesse nó amarelo aqui, começaremos a notar que muitos dos nós com os quais trabalhamos têm cores diferentes Esses azuis são as funções que estamos criando, então você sempre vê que uma função é indicada por Qualquer evento personalizado ou evento no gráfico como esse ainda é essencialmente uma função, mas eles são indicados Temos coisas como as variáveis verdes e agora temos uma função ligeiramente personalizada baseada no tempo, nossa linha do tempo de animação, que é amarela Quando os vemos com bastante frequência, podemos clicar duas vezes neles e teremos um novo recurso aqui. Então, clique duas vezes nesse nó e estaremos dentro da linha do tempo Há algumas coisas que queremos fazer. Primeiro de tudo, precisamos de uma faixa para trabalhar com uma curva de animação para começar a criar. Então, se pressionarmos a faixa positiva aqui, temos algumas opções diferentes, podemos criar uma curva flutuante, uma curva vetorial, uma faixa de eventos ou curvas de cores, essencialmente Só queremos um zero a um muito bom, essencialmente um valor normalizado que possamos rastrear Então, vamos criar uma pista flutuante aqui. E algo que é muito importante, podemos clicar com o botão direito do mouse e arrastar para mover o meio do mouse até o Zoom innit, como muitas outras navegações dentro do Mas uma coisa muito importante, antes de começarmos a adicionar quadros-chave ou pinos aqui, queremos definir a duração da nossa animação Se começarmos a adicionar pinos agora, você pode ver que estamos passando de um período de zero para 5 segundos. Então, vamos reduzir esse comprimento até um, e isso significa que estamos imediatamente trabalhando com uma linha do tempo de curva, que é o comprimento que queremos que tenha Agora, a razão pela qual eu faço isso, veremos isso um pouco mais quando detalharmos as coisas, mas não estamos pensando nisso como um momento. Não vamos fazer isso em 1 segundo. Basicamente, podemos pensar nisso como uma porcentagem. Isso seria 0% da nossa animação e isso seria 100% da nossa animação. Mostre um pequeno truque útil que eu não vejo com muita frequência um pouco mais tarde E é assim que podemos realmente adaptar isso para ser uma animação de cinco segundos, uma animação de dez segundos, uma animação de meio segundo, o que quisermos que seja. Desde que tenhamos normalizado isso para um intervalo de zero a um , podemos tratar isso mais como uma porcentagem Agora, se ampliarmos um pouco aqui, agora tornamos a curva um pouco menor, podemos segurar a tecla Shift e clicar com o botão esquerdo e criar esses quadros-chave aqui Então, se você já trabalhou com qualquer outro software de animação, eles serão bastante familiares para você. Esta será a nossa vez de que isso aconteça e a força ou o valor naquele momento. Se você está clicando aleatoriamente como eu, na verdade só precisamos de dois pontos aqui Então, vou agarrar e selecionar alguns desses pontos, esses quadros-chave, e vou me livrar deles Primeiro quadro-chave, vou definir isso para um tempo de zero e um valor de zero Então, neste momento, exatamente nenhuma animação aconteceu. E então, para o segundo quadro-chave, vou arrastar para selecionar este e defini-lo para um tempo de um e um valor de um Então, este é o nosso 100% da animação que agora está 100% completo. Então você pode começar a ver como estamos vendo isso como uma porcentagem em vez de um valor específico. Outra coisa que queremos fazer é deixar isso bonito e suave imediatamente Se fôssemos animar ao longo dessa faixa, no momento, seria uma animação muito plana, consistente e um tanto chata Então, se arrastarmos e selecionarmos os dois, clicar com o botão direito do mouse em qualquer um dos quadros-chave e definir isso como Automático, isso nos proporcionará uma boa suavização na entrada e na saída Agora você pode brincar com eles, se quiser. Você pode exagerar quando chega pela primeira vez, ou pode ser muito lento quando chega pela primeira vez E esse é um dos benefícios mais interessantes de trabalhar com esses quadros-chave como esse: podemos brincar com a animação para torná-la mais estilizada, mais caricatural, o que você estiver procurando Mas acho que vou continuar assim. A última coisa é que essa faixa zero ou nova faixa zero é algo que também podemos ajustar Então, vou clicar aqui. Vou pressionar F dois para renomear isso, e vou dar a isso o nome de Alpha Porque quando começarmos a realmente animar nossos aviões para voar, essa será essencialmente a hora extra do Alpha que estamos rastreando , em vez do valor rotacional específico E isso é que em muitos exemplos, trabalhando com cronogramas, você pode ver pessoas animando diretamente a localização ou rotação dos valores vetoriais reais durante um período específico de tempo, e espero que você veja até o final disso como isso pode ser bastante inflexível, porque, novamente, se animar algo que leva exatamente 7 segundos, que leva exemplos, trabalhando com cronogramas, você pode ver pessoas animando diretamente a localização ou rotação dos valores vetoriais reais durante um período específico de tempo, e espero que você veja até o final disso como isso pode ser bastante inflexível, porque, novamente, se animar algo que leva exatamente 7 segundos, e você Eu fiz isso em todos os XY e Z dos valores de localização ou rotação, e então você decide que, na verdade, isso é girar demais e precisa levar metade do tempo Você precisaria entrar, alterar o comprimento da faixa, mover todos os quadros-chave, e isso pode se tornar um pouco complicado e demorado Onde está isso? Podemos definir isso apenas uma vez e, em vez disso, temos controle total da animação em nosso código real. É isso mesmo. Isso está praticamente pronto. Portanto, temos nossa curva pronta para fornecer um valor alfa ao longo do tempo. Então, se clicarmos em compilar e voltarmos ao nosso gráfico de eventos aqui, tudo o que isso fez foi simplesmente colocá-lo em uma guia dentro da linha do tempo de animação que criamos Então, vamos voltar ao gráfico de eventos. Então, para definir nossa animação primeiro lugar, a partir do nosso pino de atualização, lembre-se daquela que está constantemente em execução agora até que a animação termine, queremos chamar a função set actor Location a partir daqui. Isso será o resultado de um lp, novamente, então vamos usar a função larping que vimos antes Portanto, nossa interpolação linear entre dois vetores, não a interseção dois ou qualquer coisa extravagante, basta apontar A para o ponto B com um alfa Então, você pode realmente ver que o motivo pelo qual chamamos isso de Alpha é que podemos conectá-los diretamente e já temos parte da resposta aqui apenas com base nas convenções de nomenclatura Então, só precisamos calcular ou descobrir qual será o ponto A e qual será o ponto B. Para dividir isso como um conceito, ponto A será simplesmente o local de desova. Então, de onde quer que comecemos , quando aparecermos, será o ponto A. Então, queremos chegar a um certo número de unidades à frente desse ponto de desova, que será nosso ponto B, algo que confunde bastante as pessoas quando trabalham com animações ocultas e é confuso porque parece que está parece Mas quando você pensa sobre isso, o que estou prestes a mostrar seria na verdade, meio que confundir um pouco a animação Então, o que algumas pessoas fariam quando estivessem trabalhando pela primeira vez com interpolações lineares é que sabemos que o ponto A é nosso ponto de partida Assim, podemos clicar com o botão direito do mouse e pesquisar Obter localização do ator. Para muitas pessoas, pode fazer sentido que passemos do nosso ponto de partida para um ponto final E poderíamos dizer que o ponto final, por exemplo, seria simplesmente onde estamos agora mais uma unidade vetorial em uma determinada direção Então, se pegarmos onde estamos no ponto de partida e projetarmos , digamos, 300 unidades à frente, é aí que queremos terminar. Esse seria essencialmente nosso ponto final. Agora, isso não funcionaria de qualquer maneira, mas apenas para colocar rapidamente um código para mostrar que, poderíamos dizer algo como sabemos que X está para frente, então poderíamos obter a localização x mais 300 unidades para frente no X. Parece que poderia ser nosso início e fim E eu queria abordar isso e por que não vamos usar isso, exatamente porque vejo isso em muitos projetos de estudantes e novos projetos de desenvolvimento, porque, como mencionei, isso meio que faz sentido. Temos nosso ponto de partida e nosso ponto final com base nisso Mas o que as pessoas não estão considerando quando estão fazendo isso é que isso não é disparado apenas uma vez Acho que é aí que as pessoas ficam um pouco confusas. Eu imagino que isso seja demitido apenas uma vez e esse valor permaneça o mesmo. Então, se começarmos em 000 e adicionarmos 300 a isso, esperaríamos ter 30000 como ponto final Mas o que realmente está acontecendo é cada quadro está sendo chamado, e isso está sendo verificado novamente Então, se começarmos em zero, zero, zero e depois movermos algumas unidades, digamos que movemos cinco unidades. No próximo quadro, quando isso esfriar, estamos agora em 500 Então, isso significa que o endpoint será 30500 em vez disso. Então, esses dois valores se movem continuamente. Vamos animar apenas por 1 segundo ou por quanto tempo for, de qualquer forma Isso significa que chegaremos ao fim, então parece que as animações estão acontecendo, mas sempre parecerão um pouco erradas, e talvez até um pouco imprevisíveis porque esses dois valores são constantemente verificados e atualizados e aplicando um resultado de lp diferente no final do cálculo, se isso fizer sentido Foi só para apresentar por que precisaremos nos dar um pouco de espaço, criar algum espaço aqui. E o que queremos fazer é garantir que esses valores sejam armazenados e imutáveis Então, não é uma coisa difícil, mas eu só queria destacar que isso acontece com relativa frequência, e eu posso ver, eu acho, por que as pessoas fariam isso. E é algo que você deve observar sempre que tentar criar sua própria animação ou personalizá-la posteriormente Lembre-se de que um loop precisa de um início e um alvo constantes para ser animado sem problemas entre eles Então, o que vamos fazer em vez disso é pegar isso, então vou cortar o Controle X e colar a localização do ator get. Vamos promover isso como uma variável e chamaremos isso de um local inicial. Então, claro, conecte isso, e então faremos uma coisa muito parecida aqui. E, como mencionei, isso não funcionaria qualquer maneira porque estamos apenas adicionando uma unidade. Na verdade, não estamos levando em consideração a direção para a qual o avião está olhando, então precisamos fazer um pouco mais do que isso de qualquer maneira. Mas mesmo que fizéssemos todo o processo, ainda assim não funcionaria. Então, vamos mover isso, pegar isso, então recortar e colar isso aqui. Ainda podemos fazer uso de um monte disso. Agora, a primeira coisa é lembrar que os inimigos também querem usar isso e serão atacados quando aparecerem Portanto, não queremos que eles sejam animados na tela como o jogador. Queremos que eles sejam animados com base na direção para a qual estão voltados. Então, o que vamos fazer é pesquisar o vetor direto do ator G. Portanto, isso obterá a direção em que o ator está sendo girado ou voltado atualmente Lembre-se daquela flecha que aplicamos ao projétil. Basicamente, verificarei qual direção a flecha está voltada Em seguida, queremos multiplicar isso por um valor. Então, vamos pegar o vetor direto, que é uma direção, não um valor, então isso será algo como 11 e um ou 100 se estiver voltado para frente ou menos 100 se estiver voltado para trás, por Vamos multiplicar a direção, não a posição real do vetor, é por isso que podemos multiplicar Vamos multiplicar isso por um flutuador, então vamos clicar com o botão direito do mouse no pino aqui, transformá-lo em um flutuador, e ainda podemos pegar esse valor de 300 unidades Então, queremos mover 300 unidades na direção para frente. Podemos então fazer uso disso. Então, queremos pegar esse valor e adicioná-lo a outro vetor. E, de fato, vamos nos livrar desse. Portanto, essas notas não serão mais necessárias, apenas para manter as coisas bem arrumadas, e vamos arrumá-las um pouco E o que queremos levar é que, para onde quer que comecemos, queremos nossos XY e Z da nossa posição inicial. Mais 300 unidades na direção para frente. Então, multiplicando nosso avanço para obter um negativo ou um positivo sobre se estamos voltados para frente ou para trás e o X, vamos pegar isso e dividir alguns Então, a primeira coisa para tornar isso um pouco mais fácil ler é transformar esse pino em uma variável e nomear esse local de destino. Podemos clicar com a tecla Alt e clicar com o botão esquerdo para baixo. Vamos dividir o pino da estrutura aqui. E agora temos todos os nós de que precisamos. Podemos arrumar isso um pouco. Na verdade, queremos que nosso primeiro pino seja nosso local de partida Então, novamente, apenas por preferência pessoal, vou controlar e arrastar o local inicial e substituir este. Então, podemos pegar onde começamos mais um deslocamento na direção em que estamos olhando pelo número X de unidades Isso nos moverá 300 unidades no X, é o que estamos vendo aqui porque X é quatro. Então, se pudéssemos obter o vetor get actor up, e se o conectássemos em vez disso, isso aplicaria um deslocamento no eixo z simplesmente porque Z está dentro do irreal X está para frente, Y está para o lado. Portanto, podemos obter diferentes posições vetoriais com algumas funções incorporadas aqui. Só queremos considerar seguir em frente. E então não podemos usar o valor total aqui porque queremos manter nossos Y e Z consistentes independentemente de onde estamos girando ou nos movendo aqui Então, vou pegar o local inicial novamente, duplicar isso aqui embaixo, dividir o pino da estrutura E podemos conectar o Y e o z a esses valores aqui, é por isso que eu dividi isso há pouco. E então, qualquer que seja esse valor, então, o cálculo de até onde queremos avançar em nossa direção local para frente, vamos dividir essa estrutura também, e esse será o nosso valor X que queremos. Então, lembre-se, isso é apenas calcular o X de qualquer maneira, então podemos pegar esse valor X. Essa será a quantidade de unidades para a qual queremos voar no valor X ou futuro. E esse será nosso local de destino. Então, vamos conectá-los. Talvez precisemos arrumar as coisas e movê-las um pouco, mas está tudo bem Podemos simplesmente mover isso para baixo e voltar e resolver isso um pouco mais tarde O principal é que agora podemos voltar ao nosso loop. E, novamente, isso está deixando as coisas claras e claras agora. Vamos dar a isso nossa localização inicial e nossa localização de destino como os argumentos A e B. Então, se entrarmos, provavelmente poderíamos testar isso apenas para ter certeza de que algo está definitivamente acontecendo aqui. E podemos ver que o avião do jogador está definitivamente deslizando um pouco para frente , assim como o avião inimigo Então está deslizando para dentro e depois está se movendo de um lado para o outro. Assim, podemos ver que a animação inicial está funcionando da mesma forma para o player, o que significa que provavelmente queremos começar nosso player e iniciá-lo um pouco mais para trás. Na verdade, podemos simplesmente vir aqui. Outra coisa que você talvez não conheça. E isso é muito útil, pois podemos pegar nossa localização porque sabemos que é aqui que queremos chegar neste ponto da tela e podemos digitar aqui -300 Então, se digitarmos -300, isso realmente funciona como uma equação matemática, então isso nos dá -190 -300, e obtemos exatamente menos 490, que será nosso ponto de partida, e então voaremos e terminaremos exatamente onde estávamos Então, isso realmente parece um pouco mais interessante. Eu acho que isso parece muito legal. Então, isso é definitivamente um bom começo. E você pode ver, esperançosamente, como toda essa matemática está se encaixando e funcionando E, novamente, fizemos esse trabalho considerando o vetor dianteiro do ator. Então, a forma como ele foi girado, e só para recapitular por que isso é relevante, é porque, quando geramos os inimigos, os giramos 180 graus para coincidir com a direção de apontamento de nossa classe de Então, eles estão avançando em relação ao fato de apontar, o que significa que tudo está sendo animado da maneira correta Então essa é a primeira parte do quebra-cabeça. A segunda parte tornará isso ainda mais interessante, fornecendo também um deslocamento de rotação Então, depois de definir a localização do ator, queremos afetar apenas o elemento visual da rotação, porque não queremos mexer com o colisor de esferas e mudar potencialmente a forma como os atores Então, vamos fazer disso uma mudança visual em vez de uma posição ou mudança real. Então, para fazer isso, geralmente obtemos coisas como, vez disso, usaremos a malha estática. Vamos arrastar isso para o chão, vamos tirar isso daqui e vamos procurar uma rotação mundial definida. Algo muito parecido, mas agora estamos apenas afetando a malha. E isso é muito melhor porque, de qualquer forma, não estamos fazendo nenhuma colisão ou nada nenhuma colisão ou nada importante com a malha Isso está aqui apenas para fazer coisas visuais, e isso é uma mudança visual Então, conectaremos isso para que seja chamado imediatamente e faremos algo muito semelhante Vamos pegar nosso Alpha e fazer um loop para o rotador Então, vamos partir daqui e procurar o loop novamente, p rotator, e novamente, obter a mesma coisa, A e B com um Alpha Isso é totalmente opcional. Você pode promover o Alpha a uma variável apenas para uso nessa função. Outra coisa que eu quero apresentar, porém, é que poderíamos simplesmente fazer isso. Eu cliquei duas vezes no fio. E, novamente, só para manter as coisas um pouco mais organizadas, vou conectar os Alphas dessa maneira Como essas são as únicas duas vezes que vamos usá-lo aqui, acho que talvez tornar uma área variável apenas para esse evento único de incêndio, talvez um pouco exagerado Então, vou apenas apresentar o uso de nós de reenraizamento. Isso ainda o mantém um pouco organizado e fácil de visualizar e trabalhar E então, para o A&B, faremos algo muito semelhante aqui novamente, mas obteremos os valores de rotação Então, talvez você queira começar a arrumar algumas das coisas aqui É aqui que, como mencionei as sequências podem ser muito boas Então, um corte muito rápido aqui. Queremos potencialmente começar a monitorar o que estamos fazendo para inicializar valores, essencialmente, quando estamos definindo e fraturando valores no início Isso normalmente é chamado de inicialização. E acho que posso separar isso da nossa animação real da linha do tempo Tão simples e simples que, novamente, esses fatores de referência realmente não demoram muito. Se puxarmos o pino de execução aqui e procurarmos por uma sequência, isso a conectará automaticamente para. Então, na verdade, não estamos mudando nada. Novamente, isso é apenas organizar a ordem em que as coisas são tratadas Vou simplesmente soltar esses nós aqui e, em seguida, moverei a animação para o fim. E o que faremos é garantir que todas as variáveis estejam prontas primeiro e, depois de rastrearmos todas as variáveis que usaremos na primeira, chamaremos nossa animação para ser reproduzida Então, novamente, na verdade, tudo o que isso está fazendo é manter as coisas um pouco mais organizadas, fáceis de ler e trabalhar Isso significa que agora podemos começar a remover alguns deles porque queremos todas essas verificações baseadas em localização primeiro. Então, isso está mantendo nossa posição inicial ainda. E depois disso, também vamos querer começar nossa rotação inicial. Então, a partir daqui, podemos pesquisar rotação do mundo G na malha estática, da mesma forma que fizemos anteriormente. Vou arrastar nossa malha estática, usaremos a rotação mundial G. E, como fizemos com os locais, vamos pegar esse valor e promovê-lo para uma variável. E isso é exatamente pelo mesmo motivo. Quando estamos usando isso em uma animação, não queremos que esse valor mude com o tempo. No entanto, começamos nossa rotação quando nascemos no mundo. Esse é o nosso ponto de partida, e também teremos uma compensação permanente em relação a ele como nosso ponto alvo permanente Agora, podemos fazer isso um pouco mais facilmente. Não precisamos de um alvo real para o B. Você pode promover uma variável como alvo se quiser, mas isso é um pouco mais simples. Então, para nossa rotação inicial, vamos simplesmente colocar a rotação inicial em A, então é daí que estamos girando. E então nosso alvo. Então B, podemos simplesmente dividir o pino da estrutura aqui porque a única coisa que queremos considerar é que estamos fazendo uma rotação de 720 graus Pelo menos foi o que eles fizeram no projeto de exemplo. E, novamente, estamos apenas recriando isso de uma forma um pouco mais organizada Então, o que podemos fazer é arrastar nossa rotação inicial aqui, dividir o pino da estrutura. Sabemos que queremos que o Y e o z permaneçam os mesmos. Não queremos adicionar nenhuma rotação para cima ou de cima para baixo. Não estamos girando em torno de nós mesmos. Sabemos que estamos afirmando que a malha estática está sempre começando em uma rotação de zero porque não mudamos isso E mesmo com os inimigos, estamos girando todo o ator em vez de sua malha estática, para começar Isso significa que podemos, com muita segurança, adicionar uma rotação de 720 graus ao X, que está girando em torno de si mesmo Lembre-se do que estamos fazendo para que tudo gire dessa maneira. Estamos fazendo uma coisa muito parecida aqui. Então, se clicarmos em compilar e proteger, podemos testar isso e, novamente, isso deve funcionar Tão bom, fácil. Você pode ver que está funcionando perfeitamente bem. Então é isso que queríamos lá, uma rotação de 720 graus ou duas vezes em torno de si mesma. Se você quisesse que fosse apenas um único 360, para que eles girem um pouco mais devagar, podemos definitivamente diminuí-lo, para que seja apenas um rolo, ou você pode ficar um pouco louco, talvez fazer com que ele faça cinco rotações 360 diferentes, e ele girará algumas vezes Então você pode se divertir. Você pode brincar com isso exatamente como quiser. Como eu disse, acho que pelo projeto de referência, aquele que estamos tentando recriar, acho que foi apenas um rolo de 720 graus que eles fizeram Então é assim que podemos aplicar isso. Agradável e simples. Na verdade, não precisamos um alvo específico porque é apenas a rotação inicial com um deslocamento de 720 graus para fazer com que ela gire duas vezes Isso também preenche uma grande coisa que estávamos perdendo há muito tempo, apesar de termos o código pronto em nosso projeto E isso é que o jogador e os inimigos não deveriam realmente se mover de um lado para o outro até que tenham feito a animação esporádica Novamente, isso é apenas para fins de paridade com o projeto de exemplo. Se você jogar a partir dos exemplos de conteúdo, verá que não tem permissão para controlar e mover os navios até que eles terminem esta animação de introdução Então, podemos realmente fazer uso disso. Já temos nosso movimento ativado. Isso sempre foi verificado, então simplesmente não temos feito nada com isso. Então, agora podemos pegar isso da nossa classe base. Podemos definir isso como padrão como falso, então não permitiremos que o movimento comece. Então, se entrarmos e apertarmos play, agora estamos completamente presos, assim o inimigo, que é mais ou menos o que queríamos. E é aqui que era importante apresentar o sistema de animação para você. Porque lembre-se, eu disse que isso está nos dizendo todas as informações enquanto as animações que ainda estão acontecendo estão sendo chamadas aqui E então, assim que as animações terminarem, isso será chamado Então, agora podemos puxar a partir daqui ou podemos simplesmente arrastar o movimento B ativado. Isso nos daria um setter aqui, e poderíamos definir isso como verdadeiro somente quando a animação intra estivesse concluída Então, agora podemos entrar e testar, podemos jogar. Não conseguiremos nos mover até que a animação termine. Então, novamente, é totalmente opcional, mas apenas tentando aproximar isso da maior paridade possível com o projeto Example É um recurso que eles implementaram, então pensei em abordar isso aqui. Mas é basicamente isso. Está funcionando tecnicamente Como com qualquer coisa, eu queria mergulhar um pouco mais fundo com você. Definitivamente, essa é uma opção 100%, mas acho que é uma coisa muito, muito poderosa de se saber sobre os cronogramas e uma maneira de manipular velocidade de reprodução de nossa animação sem entrar no Agora, uma coisa que eu acho que quero fazer, apenas uma última coisa a ajustar, é pegar o nó aqui e fazer um movimento um pouco mais exagerado Ele vai meio que acelerar e depois diminuir com a animação Portanto, isso é puramente visual, mas oferece uma boa liberdade sobre a suavidade ou nitidez de algumas das animações Então, eu não quero que isso ultrapasse. Se tivéssemos uma curva como essa, ela realmente ultrapassaria o ponto alvo, que seria por aqui. Então, os pontos-alvo aqui, ultrapassariam esse ponto alvo e, em seguida, seriam animados de volta ao ponto alvo Então, isso pareceria um pouco estranho. Vamos dar uma olhada rápida. Na verdade, ficaria melhor se eu clicar em Simular. Você pode ver que o inimigo estava muito além do ponto-alvo e precisava se animar de volta Portanto, tome cuidado para não fazer nada parecido, mas eu poderia torná-lo um pouco mais nítido, para que entrássemos um pouco mais rápido um pouco difícil de ver porque há esse tempo de carregamento, mas provavelmente está tudo bem. Agora, o que eu queria apresentar, porém, é que, como mencionei, uma coisa que vejo muitos desenvolvedores fazerem é tentar isso e pensar : Ah, na verdade, 1 segundo é muito rápido. Eu quero que essa animação leve 3 segundos. Então, você precisa se levantar, ajustar seu comprimento, pegar seus quadros-chave, mover seus quadros-chave e brincar com as curvas Você pode ver como isso vai ficar muito complicado, se você tiver que continuar indo e voltando Então, não vamos fazer isso. Se você estava apenas acompanhando, pressione Control algumas vezes e retornaremos o comprimento da curva para, ou seja, o comprimento total de volta para um. O que podemos fazer em vez disso, e esse é aquele truque que eu acho muito poderoso com cronogramas, é que podemos voltar aqui e talvez logo após definirmos a localização e a rotação Podemos pegar nossa linha do tempo. As informações são na verdade, transformadas em um componente Então, se colocarmos esse componente na seção de variáveis, podemos pegar nosso Anim nos detalhes da linha do tempo e colocá-lo Então, obteremos as informações sobre Anim em. A partir daqui, podemos puxar e encontrar algo chamado taxa de jogo definida. Então, podemos ver que essa é a taxa de jogo rapidez essa linha do tempo está sendo E então, se conectarmos isso aqui, agora temos controle total porque sabemos que normalizamos isso, então fizemos isso de 0 a 1 segundo Se aumentarmos a taxa de jogo, digamos que trabalharemos com números redondos simples. Vamos dizer dois. Agora está sendo reproduzido duas vezes mais rápido, então levará meio segundo, porque se estiver reproduzindo um padrão de 1 segundo, essa é a duração. Se estiver jogando duas vezes mais rápido, obviamente vai jogar pela metade Então, toda essa animação agora será feita em meio segundo. Então, basicamente, devido ao carregamento, nem vemos isso acontecer. Eu precisaria simular. E sim, é quase impossível ver. Mas se definirmos isso para algo como 0,5, isso agora vai levar o dobro do tempo, então vai levar 2 segundos. Então, temos uma animação boa, longa e suave agora, 2 segundos para eles entrarem. Então, agora temos, com algumas matemáticas realmente básicas, controle total sobre quanto tempo isso leva Podemos reduzir isso para algo muito, muito lento, 0.1 ainda está fazendo a mesma curva. Ele ainda está fazendo a mesma animação, mas agora está levando um tempo extra com base no que você faz com a taxa de reprodução aqui. Espero que você possa ver o valor disso, como mencionei Significa apenas que nunca precisaremos voltar à nossa linha do tempo Nunca mais precisaremos ajustar a curva porque normalizamos isso para E se quisermos aumentar ou diminuir o tempo de reprodução , podemos simplesmente pegar esse valor aqui E acho que o que eu poderia fazer, acho que 1 segundo provavelmente foi um pouco rápido demais, então eu poderia definir isso para algo como 0,75 Podemos clicar em compilar e salvar, verificar novamente. Acho que parece muito bom e suave, então estou feliz com isso. Mas, novamente, você pode definitivamente brincar, ajustar os valores E esse é o objetivo geral desses tópicos, pois não estou fornecendo você um resultado específico predefinido Estou tentando mostrar todas as maneiras diferentes de expor e extrapolar alguns dos valores e variáveis com os quais estamos trabalhando e realmente tornar o projeto Então, se você quiser que eles sejam realmente rápidos e girem três vezes, você tem controle total sobre isso com as variáveis aqui embaixo Você tem o dramaturgo. E, novamente, provavelmente também é um bom momento para começar a considerar a limpeza do seu projeto Agora temos muitas variáveis. Então, talvez queiramos começar a colocá-los em categorias. Temos alguns números mágicos, então também podemos começar a promover coisas assim para uma variável. Poderíamos promovê-la para outra variável, chamá-la de algo como graus de introdução ou algo parecido. Tentando deixar isso um pouco claro. É a animação de introdução e não especificamente a rotação que queremos terminar, mas o número de graus em que ela está rolando E aqui, poderíamos ter a taxa de reprodução da animação, então vamos promovê-la para variável também. Então, isso é bom porque o principal, como eu sempre menciono com variáveis, mesmo que não estejamos fazendo nada específico com elas, é ótimo porque não precisamos nos aprofundar em nosso código Sempre queremos evitar a necessidade de entrar e mergulhar em partes codificadas de nossa lógica Em vez disso, se quiséssemos tentar algo rapidamente, poderíamos simplesmente pegar a base do avião agora. Podemos clicar em compilar, garantir que tenha sido atualizado. Podemos pegar todas as variáveis e descobrir aqui que podemos ajustar a taxa de jogo de qualquer maneira e qualquer um dos valores com os quais gostaríamos de ver algumas mudanças rapidamente Como mencionei, o mesmo acontece com C plus plus, e isso acontece em azul. Você acaba com muitas variáveis, então talvez queira começar a colocar as coisas em boas categorias lógicas ou algo parecido, mas isso seria algo para você fazer entre os tópicos. Outra coisa para você entre os tópicos, uma pequena experimentação aqui, porque acabamos de dar uma olhada rápida nas animações Definitivamente, recomendo brincar com as coisas. Veja se você consegue fazer com que isso seja reproduzido ao contrário depois de já ter sido reproduzido uma vez. Faça algo como usar eventos personalizados. Lembre-se de como podemos criar nossos próprios eventos personalizados, como podemos chamá-los de qualquer lugar. Definitivamente, poderíamos conectar algo para chamar reverso. Então, novamente, tentando evitar coisas como quando isso terminar, você verá muitos exemplos de código em segundo plano e com esse tipo horrível de lógica de loop aqui e com esse tipo horrível de lógica de loop Seria muito melhor ver algo como o evento personalizado que você criou, ter este chamado em código Então, se você quiser jogar ao contrário, algo muito simples. Eu disse: experimente você mesmo, mas acabei de mostrar as respostas reais. Mas faça coisas assim. Brinque com as diferentes propriedades e recursos fornecidos por eles. Talvez faça com que ele pare no meio do caminho, reverta a partir de um ponto diferente, em jogo com curvas diferentes, talvez ultrapasse propositalmente ou adicione quadros-chave diferentes à animação da curva e veja o que acontece em e veja Talvez até mesmo adicione um pouco de escala. Assim, você pode fazer com que pareça realmente caricatural com eles começando em uma escala muito pequena, surgindo fazendo algum tipo de escala de animação stretch de squash e terminando em sua escala e terminando Comece a se divertir e brincar com as diferentes opções disponíveis para você. Mas essas são as animações de spawn completas. As naves agora entram com estilo e, a seguir, falaremos sobre o tremor da câmera e nossos efeitos de tela. 27. 26 — CameraShakeKnockback: não está pronto. Ainda há mais detalhes que podemos adicionar a este projeto. Analisaremos as colisões e os tremores da câmera, garantindo que cada golpe pareça importante Analisaremos a retração um pouco mais tarde. Isso é um pouco mais prático do que a trepidação da câmera. Começaremos aqui. Então, para começar, vamos até nossa gaveta de conteúdo e nos certificar de que temos nossa estrutura de pastas configurada E dentro da pasta principal de Blueprints, vamos criar uma nova pasta aqui, chamaremos apenas de uma trepidação de câmera Podemos adicionar alguns tipos diferentes vibração da câmera ao nosso projeto. Portanto, podemos ter algumas intenções para as explosões, e talvez outras mais suaves para os projéteis disparados ou simplesmente Novamente, depende totalmente de você, dependendo quanto impacto você deseja causar ao jogador. Para criar uma vibração de câmera, na verdade precisamos de uma classe personalizada, que seja muito boa e fácil. Nós clicamos com o botão direito. Podemos ir para nossa aula de plantas aqui. Não tenho certeza de onde está nas categorias, mas, simplesmente, podemos pesquisar a vibração da câmera. Você pode ver que, como o Epic New é algo muito popular de se adicionar a muitos jogos, eles realmente criaram algumas classes personalizadas para trabalharmos. Queremos essa aqui, a base de vibração da câmera. Temos algumas opções antigas e uma versão personalizada, mas vamos trabalhar com versão básica rudimentar, clicar em Selecionar e chamaremos isso de BP Underscore BP Vamos clicar duas vezes para abrir isso e, na verdade, não precisamos do gráfico de eventos em segundo plano aqui. Então, vou fechar isso rapidamente porque uma maneira muito simples de voltar à visualização somente de dados em visualização somente de dados em alguns Blueprints é fechá-los e clicar duas vezes para reabri-los E tudo o que realmente precisamos ver são as propriedades de vibração da nossa câmera aqui. Não programaremos nada, então podemos simplesmente trabalhar com as propriedades predefinidas fornecidas A principal coisa que queremos mudar é que temos o padrão de vibração da raiz definido como nenhum. Vamos deixar isso lá embaixo e procurar por Perlin. Isso está fornecendo uma boa randomização usando alguns padrões de ruído Perlin pré-gerados Se você se lembra desses atalhos que mencionei há muitos tópicos, é aqui que coisas como segurar a tecla Shift e soltar as setas aqui podem ser Então, se clicarmos novamente com a tecla Shift pressionada, isso desdobrará todas as categorias E se quisermos dobrar tudo isso de volta, podemos segurar a tecla Shift e clicar neles novamente. E, novamente, isso os afasta muito bem. Então, como há tantas propriedades diferentes que queremos acessar, vou dobrar tudo, para que possamos examiná-las em ordem e descobrir o que, para começar, temos o multiplicador de amplitude e frequência de localização Vou deixá-los de uma só vez. Isso pega toda a animação gerada e adiciona um multiplicador à amplitude e frequência no X, no Y e no z para a rotação, localização e campo de visão Isso é útil se quisermos fazer algumas mudanças realmente grandes, mas geralmente queremos trabalhar por ponto. Portanto, devido ao pequeno impacto que estamos causando no momento, talvez toda vez que um projétil atinja algo, queiramos que a câmera se mova um pouco para frente apenas para mostrar que algum impacto foi recebido Então, sabemos que para frente é o X, então podemos pegar isso e começar a adicionar alguma amplitude à localização X. Se adicionarmos um valor de 200 aqui, isso é uma amplitude, um tipo de força que é aplicada. E então a frequência é quantos solavancos para frente e para trás isso Então, se mantivermos isso como um, será como um único golpe toda vez que um projétil atingir Você deve evitar adicionar muita frequência em muitos casos, porque é isso que fará com que as pessoas se sintam um pouco enjoadas Isso tornará um pouco mais difícil ler e avaliar o que está acontecendo na tela. Mas, novamente, tudo isso pode se resumir à preferência pessoal, tipo de projeto e ao estilo geral que você usava. Vou deixar isso como um só para a frequência, e tendo isso em mente, podemos passar um pouco mais rápido para os outros eixos aqui Então, eu quero que isso oscile de um lado para o outro um pouco mais, mas com menos intensidade Então, vou definir isso para 40 e dez para a frequência. Novamente, dez pode ser muita oscilação lateral, mas ao vender isso para algo maior, podemos voltar e refinar mais tarde, se isso for Para a rotação, vou deixar tudo isso como padrão. Muitas vezes, não queremos girar a câmera, o que é quase mais do que qualquer outra coisa, que quase certamente causará algum tipo de distúrbio no feedback visual Você definitivamente sentirá algum enjôo A menos que você tenha um bom motivo para usá-lo e saiba o que está fazendo. Então, vou deixar a rotação completamente intocada. Semelhante ao campo de visão, você pode brincar com eles se quiser, mas não quero ajustá-los demais. O último detalhe aqui é a mistura durante a noite, quanto tempo eles levam para atingir o pico e quanto tempo leva para e quanto tempo leva passar do pico para não serem animados e, em seguida, Então, vou fazer isso durar 3 segundos. Será um impacto relativamente pequeno, mas durará por um período razoável de tempo. Então, tivemos que compilar e salvar. Essa é basicamente a nossa configuração de classe de vibração de câmera. Agora, com a configuração da propriedade principal aqui, enquanto estamos fazendo isso, podemos também criar algumas opções diferentes para descartar e testar as coisas. Então, vou reduzir a vibração da nossa câmera, pressionar control, na verdade, para duplicar isso, e vou criar uma chamada média Vou duplicar esse e chamá-lo de grande. Então, talvez possamos ter diferentes tipos de impactos, especialmente em coisas como as explosões Eu provavelmente gostaria de um impacto um pouco diferente, mas muito maior porque, de qualquer forma, isso não acontece com muita frequência, e então podemos alterar ou iterar entre os impactos pequenos e médios por diferentes motivos Por um preço médio, eu vou entrar aqui. aumentar a amplitude para algo como 500, talvez aumente a amplitude no Y para 90, 15 na frequência. Novamente, sempre podemos voltar e alterá-los se algum deles for demais. Acabei de perceber , na verdade, pensando em como eu queria configurar isso. Em câmera shake small, acho que queremos que a duração seja de 0,3, não de 3 segundos. Com duração de 3 segundos. Se você me imaginar falando agora são cerca de 3 segundos. A tela teria oscilado durante toda a frase, que é um pouco demais. Então, vamos compilar isso, reduzir isso para 0,3 porque não queremos superestimular as pessoas visualmente . Então, podemos fazer a mesma coisa aqui. Vamos definir isso para 0,3. Talvez possamos fazer isso de 0,4 porque há mais tremores acontecendo. Pode haver motivos para que ele permaneça por mais um pouco Então, vamos definir isso para 0,4. A mesma coisa para grandes. Queremos que este realmente tenha um grande impacto, porque haverá a sensação de que está bem perto da câmera quando algo realmente explode, esses grandes efeitos de partículas estão sendo Então, este faz sentido , pode ser um pouco mais forte. Então, na verdade, vou mudar o multiplicador geral aqui para realmente dar um impulso a isso Então, vamos configurar isso para cinco e, em seguida, a amplitude, eu vou configurar isso para A amplitude Y, coloque isso em 160. Vou deixar a frequência às dez. Não queremos muito que isso ande de um lado para o outro. Acho que o prazo, novamente, talvez seja mais ou menos definido para 0,5 segundos ou apenas dê a eles pequenos incrementos, para que todos fiquem visivelmente diferentes quando estamos fazendo nossa reprodução Então, novamente, não há certo ou errado. Posso ter atingido valores muito altos, talvez até altos demais, mas sempre podemos refiná-los e trazê-los de volta, dizendo que definitivamente são altos demais. Eu disse 900, mas em até 9.000. Seria quase impossível ver o que estava acontecendo, então vamos nos certificar de diminuir o tom. Não diga isso muito alto. Portanto, não temos três intensidades para testar e só precisamos implementar isso em nosso código Tão bonito e simples, é um sistema pré-construído pronto para nós. Vou voltar para a base do avião BP Underscore. Vou mantê-los abertos caso eu queira voltar e ajustar os valores a qualquer momento Dentro da base de aviões da BP, uma das mais óbvias a serem usadas primeiro seria a função de morte Então, temos nossa função handle Death. Ainda temos o que fazer aqui, se você precisar encontrá-lo dessa forma. Então, eu tenho meu comentário a fazer, e esse é o efeito final que eu sabia que queria voltar e implementar. Então, podemos retirar o pino de execução aqui. Procuraremos uma função chamada Play World camera shake. Você pode ver isso aqui. Isso é muito semelhante aos nossos três sinais D, ou seja, nossos sinais direcionais e até mesmo nosso sistema de partículas Então, novamente, quando você começa a aprender como fazer um dos diferentes recursos do Unreal, você também entende um pouco como fazer as outras coisas, se isso fizer sentido Então, temos aqui, por exemplo, o epicentro, que é o local a partir do qual o shake começa a tocar Então, de forma simples e simples, vamos duplicar isso, obter a localização do ator e conectá-la Portanto, a vibração da câmera deve começar a partir da qual a nave Aber acabou de explodir, e então ela meio que rasgará a luz em direção à câmera, é o tipo geral de Fazemos isso com base em um raio, então o raio interno é onde isso será mais forte Então, se a câmera estiver ao lado do avião que explode, ela obterá toda a força do avião que treme a câmera Então, vamos definir isso para algo como 2.000 unidades de raio. E então, o raio externo é onde qualquer coisa fora dessa zona provavelmente não será afetada pela vibração da câmera ou, se estiver muito próxima, poderá ocorrer o tipo final de oscilação final E acho que vamos definir isso para algo em torno de 5.000 e, novamente, você pode brincar com eles se estiver acontecendo muito ou muito intenso, você pode mudar o raio e brincar com isso Como eu disse, para as explosões, quando as naves reais estiverem explodindo, vamos soltá-las e procurar o sublinhado da BP, Cam Shake Lidge, então esse será o tremor da nossa Cam Shake Lidge, então esse será o tremor da Podemos clicar em compilar e salvar, e podemos apenas testar este porque definitivamente temos a funcionalidade pronta para Ok, então foi isso que eu quis dizer quando algumas delas podem ser um pouco intensas demais Então, isso vai ser fácil de corrigir. Acho que o rádio deve estar bom porque a câmera está apenas verificando duas vezes. Se a partida do jogador for 130 no z e a câmera tiver 2.400 unidades no Z, isso significa que, de qualquer forma, estamos um pouco fora do raio interno de qualquer uma das explosões Portanto, devemos ter uma trepidação um pouco reduzida da câmera. O que podemos fazer. Acho que talvez eu tenha ido direto para o multiplicador um pouco alto demais. Mas, como mencionei, essa é, na verdade uma abordagem muito comum para esse tipo de coisa: dobrar, triplicar ou quadruplicar o que você acha que um valor razoável pode ser e depois revisá-lo depois de testá-lo Isso evita que você faça muitas alterações incrementais muito pequenas que geralmente podem levar ainda mais tempo Então, parece um pouco melhor, talvez 1,5, para que possamos fazer uma substituição maior, mas manter as configurações gerais aqui iguais E eu acho que está tudo bem. Então, não vou passar muito tempo refinando isso Isso agora pode ser assistido. Eu posso ver e continuar jogando isso com Too Perturbed, então vou deixar isso como está Então essa é a nossa grande vibração de câmera e, novamente, você pode refiná-la e alterá-la completamente para se adequar ao seu projeto conforme desejar Então chegamos à questão dos nossos projéteis. Devemos fazer isso tremer toda vez um projétil é disparado ou toda vez que um projétil atinge algo ou Isso seria essencialmente um tremor constante, que poderia ser um tanto nauseante Então, acho que nesse tipo de projeto, uma abordagem melhor pode ser criar algo que notifique o jogador de que ele foi atingido, pois dessa forma estamos aprimorando esse visual, mas na verdade o implementando na jogabilidade Portanto, uma das coisas mais irritantes para qualquer jogador de jogos com combate envolvido é ser atingido, mas não perceber que sofreu dano ou ser capaz de diferenciá-lo do dano bronzeado do inimigo Então, isso meio que resolve dois problemas diferentes porque, no momento, recebemos um pequeno feedback se formos atingidos porque temos picos em nossa nave Mas não está muito claro se estamos perdendo danos ou saúde até sermos destruídos. Então, isso pode ser um bom tipo de solução para isso. Isso comunica que o jogador está sofrendo dano. Isso não mostra que o inimigo está sofrendo danos, mas ele está prestes a explodir de qualquer maneira Portanto, não é tão importante porque eles não têm muita saúde pela qual passar. E ainda estamos dando esse feedback visual de que as partículas estão impactando o avião inimigo Então, isso vai ficar meio claro. Uma boa maneira simples de fazer isso, então, com isso em mente, é ir para nossa aula de projéteis Queremos fazer tudo relacionado a projéteis na classe de projéteis Se você ainda não está aqui, acontece que eu estou ao lado dos meus comentários para fazer, então vamos fazer isso para fazer comentários novamente. E, na verdade, vou ser um pouco preguiçoso, como fiz no passado Eu vou para a aula de avião. Vou pegar todo esse código, para obter a localização do ator e a câmera do Playworld Pressione control em S para copiar isso. Enquanto estou aqui, também posso me livrar desse comentário. Agora, na verdade, fizemos toda a nossa lista de tarefas. Temos todos os efeitos diferentes que vamos implementar, então vou me livrar deles. E então voltaremos para a base do projétil, colocada no play world camera shake, moveremos as coisas um pouquinho E a lógica é muito parecida. Então, queremos fazer a mesma coisa novamente. Queremos obter o local que o impacto acabou de acontecer e vamos jogar a partir daí, no mesmo raio, porque ainda queremos que o mesmo tipo de câmera caia Mas tudo o que vamos fazer é talvez verificar se o pequeno impacto é grande o suficiente para começar, e talvez queiramos mudar isso para médio. E isso é outra coisa. Se você acha que isso não é impacto suficiente, tente alterá-lo. Então, cada golpe dá uma sacudida, mas talvez nas naves inimigas, seja apenas uma pequena sacudida, e na nave do jogador, seja uma sacudida média. Novamente, depende totalmente de você. Agora temos aulas diferentes. Você pode brincar com isso e ver o que funciona. acho que, para o meu projeto, vou deixá-lo apenas para indicar que os jogadores estão sofrendo danos. Agora, há uma coisa para a qual precisamos abrir um pouco de espaço, e eu quero, novamente, mostrar a vocês o tipo de maneira pela qual eu vi pessoas decifrarem seus códigos acidentalmente Então, sabemos que temos uma condição aqui. Só queremos que isso aconteça se estivermos atingindo a nave do jogador. Então, o que você pode fazer é jogar um galho aqui, então vamos fazer uma verificação do galho E queremos verificar. Já sabemos que estamos rastreando o que estamos atingindo, então podemos pegar nosso ator sobreposto Não acho que nada disso seja um conceito novo para você. Então, vamos duplicar isso, então eu vou pegar meu ator de sobreposição, certificando-me de que estou segurando aquele Pressione o controle, na verdade, para duplicar. E queremos verificar se a coisa que estamos sobrepondo, sabemos que não é o proprietário, já superamos esse Mas se for igual a, e já vimos isso antes, podemos usar o get PlayerPawn Então, se for igual ao que está atualmente rastreado como PlayerPawn, somente se isso for verdade, queremos jogar o Então, nós apenas aumentamos um pouco isso. E você provavelmente já viu que esse não é exatamente o maior problema ou problema a ser resolvido. Alguns de vocês já devem ter visto, mas se isso não for verdade, se for falso, se for outra coisa, estamos bloqueando essa chamada de função aqui. Então, lembre-se de que isso é algo com o qual você só precisa se familiarizar com a ordem de operação, o controle de fluxo do seu código. Em C plus escrito, é muito mais fácil porque usaremos declarações FL que podemos simplesmente retirar de dentro do corpo da função. Então, é muito mais fácil acompanhar isso. No Blueprints, é muito fácil interromper acidentalmente o resto da funcionalidade quando uma única verificação de ramificação é feita Então, eu só queria mencionar que, se você está seguindo esse fluxo que está apenas atualizando e melhorando seu código ou adicionando recursos, é muito fácil acidentalmente, sempre que o inimigo for atingido agora, não nos destruiríamos Então, algo que poderíamos fazer em vez disso é, novamente, resolver tudo isso com o uso de uma sequência. Então, se eu seguir em frente, e isso é apenas para tentar enfatizar a importância de pensar na limpeza do código, não apenas para perder tempo e fazer com que o código fique bonito no Blueprints, mas também porque isso literalmente facilita a leitura e a manutenção e garante que você não esteja cometendo erros realmente fáceis de cometer realmente fáceis de cometer Então, se incluirmos nossa sequência aqui e novamente, queremos pensar nisso como uma linha específica de funcionalidade, que, no nosso caso, é aplicar danos, e eu posso ficar tentado a fazer tudo o que não está relacionado ao dano, tudo o que está relacionado à reprodução de um efeito Vamos jogar na então. Então, estou apenas pressionando Control X. E vamos conectá-los Então, vamos aplicar o dano primeiro. E então, se o dano for aplicado, reproduziremos nosso efeito de partícula e reproduziremos nosso tremor de câmera, mas apenas para o jogador E então vamos fazer a última coisa. Então, novamente, isso nos dá uma boa ordem de operação. Podemos ver a ordem exata na qual nossas funções serão chamadas. E, como mencionei anteriormente, quando analisamos as sequências, o que tornaria isso um pouco mais claro é se você fizesse esses Então, essa pode ser a linha de danos. Essa pode ser a linha de efeitos, e essa pode ser a linha de limpeza ou algo parecido. E você pode se lembrar disso nos comentários Então, novamente, apenas uma mudança muito rápida e simples, e agora sabemos que, independentemente de isso ser acionado ou não, definitivamente sempre destruiremos nosso ator porque, uma vez verificado , se for chamado, ele voltará para a próxima parte da sequência e voltará. Se isso não for chamado, ele ainda voltará para a próxima parte da sequência e depois voltará para baixo. Então, o importante é que isso seja chamado de qualquer maneira. Então, agora podemos entrar e testar, e verificar novamente. Isso não está acontecendo com os inimigos. Então essa foi a explosão. Então, a outra coisa é que, se os projéteis estivessem se atingindo, isso poderia ter causado o tremor da câmera quando os projéteis também se atingissem Então, agora eu vou me deixar levar por mais nada acontecendo. Lá vamos nós. Então você pode ver se eu não estou morrendo ao mesmo tempo. Você pode ver que talvez seja um pouco difícil ser atingido, mas você pode ver a câmera tremer, o que é importante. Como mencionei, isso pode ser muito sutil. Se for esse o caso, tudo bem, porque temos nosso shake médio que podemos testar. Se realmente quiséssemos deixar claro que os jogadores estão sendo atingidos. Lá vamos nós. Então, isso dá uma indicação muito maior de ser atingido. Mais uma vez, pessoalmente, acho que o pequeno está perfeitamente bem. Talvez queiramos adicionar um pouco mais de força, mas manter a frequência a mesma ou algo assim, mas só para avisar que eles perderam a saúde, acho que está claro o suficiente. A próxima etapa será abordar coisas como materiais e criar um material intermitente que cause danos à saúde ou algo assim, se você realmente quiser visualizar Mas acho que isso já é um grande avanço relação ao que tínhamos antes , porque está apenas tornando as coisas um pouco mais visuais e um pouco mais claras O fato é que vamos adicionar rapidamente uma simples reviravolta quando aviões colidirem uns Para este, queremos lidar com isso apenas na classe de jogadores, porque essa é a única que está fazendo uma pseudofísica Então, vou fechar todas as outras guias. Acho que terminamos com os tremores da câmera e vamos entrar no player de avião de sublinhado da BP E dentro daqui, o que queremos fazer é pegar aquela esfera. Vamos até a seção de colisão no painel de detalhes e vincularemos a função on component hit aqui, como fizemos no passado E vou manter isso muito bom e simples. De qualquer forma, acho que é o mesmo projeto de exemplo, que podemos ricochetear nos inimigos e nas paredes Então, sempre que atingimos algo, não precisamos verificar o que é. Vamos apenas pegar nossa velocidade de movimento atual e multiplicá-la por um valor negativo com um pouco mais Faz com que o jogo pareça divertido e dinâmico. E o mais importante, novamente, basta dar ao jogador o feedback de que você está realmente tocando em outro objeto no mundo que tem alguma permanência Então, vamos obter a velocidade atual, como mencionei. Vamos multiplicar isso por um valor negativo mais um pouco porque não queremos simplesmente invertê-lo. Queremos adicionar uma pequena repulsa forte. Então, digamos que -1,5. E seja o que for, vamos então ajustar a velocidade atual de volta para aquela. Obviamente, isso está sendo explicado no larping de qualquer Então, a interpolação larping, que está acontecendo com nossa função geral de movimento, tentará pegar nossa nova velocidade de movimento e, em seguida, suavizá-la de volta à velocidade normal que suavizá-la de volta à velocidade normal deveria estar indo e na direção em que estamos Então, isso não vai parecer muito desagradável, eu acho. Outra coisa que poderíamos fazer aqui, embora estivéssemos fazendo muitos tremores de câmera, de qualquer forma, pensando nisso E, novamente, completamente opcional, mas é algo que vou tentar. Eu vou entrar na base do projétil. Vou copiar o código aqui, a vibração mundial da câmera, colar isso aqui, e talvez façamos uso da vibração média da câmera, então vamos deixar isso abaixo. Mesmo raio, mesmo Apicentro, e podemos simplesmente entrar e apertar play Não, definitivamente é muito pesado, eu só estava pensando que poderíamos tremer um pouco quando o salto acontecesse um pouco quando o salto acontecesse Vamos tentar fazer isso com os inimigos. Tem muita coisa acontecendo lá. Então, novamente, tentativa e erro, isso pode ter funcionado. Talvez eu tenha parecido muito legal, mas não funcionou. Talvez possamos fazer uma pequena sacudida. A principal coisa que queremos é garantir que ricocheteemos contra os inimigos também ricocheteemos contra os inimigos. Então, vamos verificar novamente. Tão bem pulando na parede. Quicando no inimigo. Acho que os inimigos estão sofrendo muito dano com nosso tremor. Eles deveriam saber que foi um golpe, não é? Tudo bem. É o jogador que morre após dois golpes. Então, sim, tudo bem com o diabo. E então, se você está se perguntando por que isso não afeta os projéteis momento, ainda podemos ser atingidos por projéteis, mas não estamos quicando Estamos apenas pulando nas paredes e nos inimigos, o que eu acho muito legal A razão para isso é voltar à nossa configuração de colisão. Então, espero que isso ajude toda a estrutura de colisão a fazer mais sentido também Portanto, lembre-se de que nossa esfera no jogador está configurada para bater. Portanto, ele está apenas verificando colisões físicas com outros objetos físicos Então, isso é fazer uma verificação de sucesso aqui dentro de nosso jogador e de nossos inimigos. O projétil, embora pareça relativamente semelhante, meio que o mesmo, isso é fazer um tipo diferente de verificação, lembre-se Isso é definido como um colisor de sobreposição. É por isso que é útil pensar em como você vai configurar seus diferentes aceleradores Isso significa que você pode obscurecer completamente os diferentes tipos de configuração de colisão para reagir e responder às diferentes contrapartes de maneiras Isso significa que não precisamos nos preocupar com os projéteis, causando qualquer empurrão ou tipo de empurrão físico para de empurrão físico Eles estão literalmente voando pelo espaço. Eles não estão fazendo nenhuma física. Eles não estão colidindo fisicamente com as coisas. Eles estão apenas verificando se há mais alguma coisa no mesmo espaço. E se outra coisa acabar no mesmo espaço, tudo o que ela está fazendo é tentar causar dano, tentar produzir alguns efeitos e depois se destruir É por isso que podemos escapar impunes. E, novamente, é claro, os limites de nível são configurados com a mesma colisão, então eles são configurados para bloquear os inimigos e o jogador Então é isso. O projeto está polido. Acho que agora parece muito mais interessante interagir com isso. Ele fornece uma experiência um pouco mais animada e interessante para interagir Novamente, muito disso se resumirá ao refinamento. Não espero que você saia do projeto, pois já dei essas etapas até agora Se você não gosta nem um pouco da vibração da câmera, ou acha que pode fazer isso um pouco mais, tudo bem Adicione, remova e altere todas essas propriedades conforme achar melhor. E isso é apenas algo para você testar e experimentar entre os tópicos e realmente começar a trabalhar com o projeto. E crie novas classes de vibração da câmera se você puder ver um caso de uso de algo que treme com mais frequência ou menos frequência, mas com mais amplitude, por exemplo O principal é que cada impacto seja adequado ao feedback que o jogo está tentando enfatizar. E é isso que fará com seus projetos deixem de parecer um tipo de jogo iniciante muito amador para algo que tenha um pouco mais de reflexão, cuidado e atenção aplicados a todos os diferentes elementos com os o jogador interagirá Outra coisa que você pode tentar é experimentar a onda em vez da pérola no ruído enquanto a câmera treme e qualquer um dos outros tópicos que eu meio que mencionei, mas não teremos tempo de nos aprofundar em cada ressalva de todos os diferentes processos Feito isso, porém, temos nossa sacudida, recua. O peso e o impacto do campo estão ficando bem reais agora, que deixa o fim da criação de uma interface de usuário para lidar com todo o ciclo do jogo. No momento, os jogadores ficam meio que presos em um vazio infinito se forem destruídos, e obviamente não queremos que seja esse o caso 28. 27 — UI: Ok, então estamos no tópico final. Essa será a tela de fim de jogo, a interface do usuário, fornecendo um sistema de reinicialização e uma saída adequada. Idealmente, teríamos alguns botões para pressionar. Mas vamos manter essa interface de usuário agradável e simples. Você termina. Você pode pressionar o botão I para reiniciar e depois voltar ao jogo. Em um projeto maior, talvez você queira adicionar uma tela de menu ou algo parecido. Mas com isso, você terá um jogo completo e jogável. A primeira coisa que queremos analisar é o conceito de widgets Portanto, o UnrelEngine lida com sistemas de menus e sobreposições de interface de usuário, pressionamentos de botões e coisas assim por meio de algo chamado classe Então, dentro da nossa estrutura de pastas, vou criar uma nova pasta, e vou chamá-la de widgets ou UI Muitas vezes, você verá isso como um desses dois quando estiver examinando os projetos de outras pessoas. Dentro da minha pasta Widgets, queremos clicar com o botão direito do mouse aqui Vamos para a Interface do usuário. Podemos ver aqui que temos a opção um blueprint de widget Portanto, ainda existem classes de blueprint, mas isso só nos permite colocar uma espécie de interface visual com algum código vinculado a ela Selecionaremos essa opção aqui e criaremos um widget de usuário padrão Em seguida, clicaremos em Selecionar e daremos a ele o nome de WBP para Widget Blueprint Vamos clicar duas vezes para abrir isso, e você verá que o layout é um pouco diferente. A primeira coisa é observar que no lado direito, canto superior direito, temos duas guias diferentes Temos a guia de designer, que é onde estamos agora. Isso fornece um layout visual e um sistema de tela muito bom para arrastar e soltar elementos diferentes para configurar a forma como isso será exibido na tela. Em seguida, temos o gráfico, que é nosso editor de diagramas padrão, muito semelhante ao que você viu antes, com apenas algumas pequenas nuances Ainda no elemento designer aqui, vamos para o lado esquerdo e queremos algo chamado sobreposição dessas diferentes categorias. Você pode ver que existem muitas categorias diferentes, então vou apenas pesquisar por sobreposição E isso é essencialmente um painel para colocarmos todas as outras coisas importantes. Então, vamos inserir isso , e você pode ver aqui que esta é a nossa sobreposição na tela Só queremos ter certeza de que este é um painel de 19 por 20. Então, podemos arrastar isso e colocar isso. Eu só preciso me dar um pouco mais de espaço. Podemos soltar isso e ver que meio que se encaixa clicando nos limites aqui, e isso se encaixará Portanto, temos um painel padrão de 19 por 20. Agora, eles serão configurados para serem dimensionados e alterados com base na tela em que estão sendo colocados. Mas vamos usar o padrão, supondo que estejamos em uma tela de 19 por 20, e possamos trabalhar com base nessa premissa Em seguida, também podemos adicionar um bom tipo de visual a isso. Então, podemos pesquisar algo chamado painel de desfoque ou desfoque de fundo, e vamos simplesmente colocar isso aqui Podemos ver que a hierarquia aqui, a sobreposição, é onde tudo meio que será colocado, e então o desfoque de fundo é filho da Podemos ver se aumentamos o zoom. O desfoque de fundo é um pouco pequeno Acharemos um pouco difícil ver se pressionaríamos Play e mostraríamos isso. Então, o que queremos fazer é, no lado direito, alinhar isso à nossa sobreposição Então, se pedirmos para ocupar, preencher todo o espaço horizontalmente e preencher todo o espaço verticalmente, você pode ver que agora corresponde ao tamanho do componente pai, que é a Para a intensidade do desfoque, vou pegar esse valor aqui no painel de detalhes e atribuir a ele uma intensidade de desfoque de 15, e podemos ver que isso adicionou um leve desfoque ao nosso painel, que acho que ficará muito bonito, meio moderno e proporcionará meio moderno e proporcionará um pouco de Em seguida, queremos ver como podemos formatar o texto que queremos mostrar na tela. Então, vamos mostrar algo assim, apenas um simples texto dizendo fim de jogo e, em seguida, uma dica de ferramenta sobre como reiniciar. Uma boa maneira fácil de gerenciar vários elementos em uma única área em um menu seria usar algo como uma compra horizontal, se você quisesse que as coisas se estendessem horizontalmente pelo widget ou uma Nesse caso, vamos ficar na vertical. Portanto, se procurarmos uma caixa vertical, podemos colocá-la e garantir que seja uma consequência da sobreposição e não do desfoque do fundo Para o alinhamento deste, você pode ver que está ocupando a caixa inteira Em vez disso, vamos definir isso como linha central para as configurações horizontal e vertical aqui. Está perfeitamente bem. Podemos fazer essa escala para os elementos internos um pouco mais tarde. Os elementos, como mencionei, serão muito, muito simples para isso. Vamos apenas dar a isso um elemento de texto, então vamos pesquisar um texto e soltar nosso primeiro elemento de texto na caixa vertical. E você pode ver que realmente saiu da caixa vertical para caber no Para o texto inicial, vou configurar isso para dizer GameOver Então, com o texto selecionado, queremos encontrar nossa opção de texto aqui. Você pode ver que no momento está dizendo bloco de texto, e vou mudar isso para fim de jogo. Altere o tamanho da fonte. Então, no momento, se colocarmos nossas propriedades de fonte aqui, o tamanho é 24, e acho que um tamanho de cerca de 50 seria ideal para este. Podemos mudar o tipo de letra. Roboto bold geralmente parece um pouco desagradável. Podemos simplesmente mudá-lo para normal ou até mesmo a luz pode ficar bem bonita. Parece um pouco mais limpo. Isso agora não parece muito impactante. Talvez queiramos alterar o tamanho da fonte para algo como 60 para que pareça e soe um pouco melhor. Agora, com esse texto selecionado, podemos pressionar. Então, vamos pegar isso aqui no lado esquerdo ou duplicar nosso texto Portanto, controle, de fato, para duplicar. E você pode ver que, como está dentro dessa caixa vertical, agora está se certificando de que ela esteja alinhada verticalmente E se continuarmos adicionando elementos de texto, teremos esse bom alinhamento em uma ordem vertical Portanto, isso torna um pouco mais fácil gerenciar e trabalhar com vários elementos quando você deseja que eles estejam aproximadamente alinhados uns com os outros no mesmo lugar. Agora, para este, vou pegar o novo elemento de texto ou alterar o texto para dizer pressione R para reiniciar. Provavelmente não é o game over tela mais interessante , mas transmite a ideia. Vamos mudar um pouco o tamanho disso. Não precisa ser muito impactante quando o jogo termina. Então, vamos dar a isso um tamanho de fonte de 30. Também poderíamos dar a eles um pouco de preenchimento. Então, se eu pegar o GameOver, em primeiro lugar, no painel de detalhes à direita, podemos dar a ele um título padrão de, digamos, dez, para que fique um pouco mais complicado E podemos fazer a mesma coisa pressionando R para reiniciar. Também vamos dar um pouco de limite a isso. E o principal é que queremos que isso seja alinhado ao centro. Assim, podemos pegar o alinhamento horizontal e garantir que ambos estejam alinhados ao centro Então, eles estão meio que colocados no meio da caixa vertical, bem arrumados, e não precisávamos trabalhar muito Outra coisa que você pode querer fazer é mudar um pouco as cores visuais. Para que pudéssemos terminar o jogo. jogadores que terminam o jogo normalmente são representados com vermelho, laranja ou algo parecido, então podemos mudar a cor aqui para uma cor um pouco mais negativa, fazendo com que ela se destaque da entrada aqui Parece um pouco mais interessante porque temos mais coisas acontecendo. algumas passagens mais sofisticadas Talvez você queira fazer algumas passagens mais sofisticadas: você pode usar suas próprias fontes com muita facilidade para desenrolar e, em seguida, basta alterar a fonte que deseja usar para torná-la um pouco mais personalizada Brinque com coisas como a ousadia, o tamanho da fonte. Você pode até adicionar coisas como contornos se quiser enfatizar certas partes Então, se eu apenas ampliar um pouco. Eu poderia adicionar um contorno de dois pixels ao redor e obteríamos um contorno elementos do nosso menu aqui Então, o que quer que você queira fazer para tornar isso um pouco mais interessante, como eu disse, vamos manter isso simples e simples apenas para mostrar que o jogo acabou e dar ao jogador uma dica sobre o que ele pode fazer a seguir. Então, vamos voltar brevemente ao sistema de entrada porque agora precisamos que algo seja acionado quando essa interface de usuário for exibida na tela. Então, se voltarmos ao nosso sistema de entrada, basta recapitular o que temos Já temos nossa chave de reinicialização. Agora, como mencionei, em um jogo completo em que você tem um sistema de menu mais complexo e coisas assim. Você pode ter diferentes classes de contexto de mapeamento de entrada. Nesse caso, limitamos tudo a uma única jogabilidade, e acho que está tudo bem porque não temos nenhum uso sobreposto, então se você quisesse usar, por exemplo, o botão Voltar em um gamepad, então B no gamepad, para ser uma entrada como pular, mas você também queria que fosse o botão de reinício, talvez você queira compartilhar isso . Portanto, se você estivesse em um menu, B seria mapeado para reiniciar Assim, você teria seu contexto de mapeamento de menu. E então, quando você está no jogo e era pular, você teria seu contexto de mapeamento de jogabilidade. Nesse caso, acho que apenas usar este seria perfeitamente adequado. Então, vamos voltar ao nosso GameOver e só queremos fazer aquela encadernação que fizemos anteriormente Então é aqui que entra o lado do código do nosso menu, e é aqui que parte da flexibilidade muito interessante do sistema de entrada aprimorado torna coisas assim muito mais fáceis do que costumavam ser. Definitivamente, era possível com o sistema antigo, mas isso é definitivamente um avanço. Navegaremos até o gráfico aqui, e eles são bastante semelhantes aos que vimos antes. Portanto, temos uma marca de evento e, nesse caso, não faremos nada em nosso menu, então podemos nos livrar disso. Portanto, a construção do evento é essencialmente a mesma do início do jogo. Isso acontecerá assim que o jogo começar e o menu surgir Então, quando mostrarmos o menu na tela , serão cinco uma vez. Pré-construção, você precisa ter um pouco de cuidado. Isso é útil para alterações no editor. Portanto, poderíamos codificar coisas para que pudéssemos receber atualizações ao vivo do editor, mas você precisa ter cuidado aqui, pois se estiver referenciando outras classes ou fazendo coisas fora do menu, isso pode causar problemas se você ainda não estiver no modo de jogo Então, para evitar confusão, vamos nos livrar dessa, e vamos pensar nisso como nosso objetivo em Começar a jogar, o que queremos fazer ou construir um evento é voltar ao controle do jogador e fazer exatamente o que fizemos anteriormente. Queremos encontrar o subsistema aprimorado do player local de entrada Este aqui com o ícone de função roxo rosado logo E, novamente, da mesma forma que fizemos antes, vamos adicionar o contexto de mapeamento. Então, várias classes podem ter o mesmo contexto de mapeamento, então vamos ter o contexto de mapeamento agora em nossa classe de jogador, que está manipulando a entrada para se movimentar e disparar Podemos adicionar esse mesmo contexto de mapeamento ao nosso menu. Então, quando isso for gerado, ele também rastreará os pressionamentos de botão relevantes Agora, nesse caso, tudo bem porque o pressionamento relevante do botão será apenas uma reinicialização do sublinhado IA Então, podemos clicar com o botão direito aqui. Vamos procurar por IA underscore restart Queremos o evento novamente, então, quando algo acontece, obtemos o arquivo pin de execução de quando ele é pressionado. Nós simplesmente queremos recarregar o nível em que estamos atualmente e estamos apenas reiniciando o jogo Nós só temos um nível, então isso é bom e simples. Há uma função que podemos usar para fazer isso, um recurso embutido no Unreal Podemos usar o nome do nível get current. Então, essa função aqui, conecte-a para começar. Então, novamente, quando pressionado uma vez, isso retornará o nome do nível em que estamos atualmente, que, lembre-se, é chamado apenas de principal. Então, poderíamos fazer isso codificado e simplesmente digitar o nível principal do nível que estamos prestes a recarregar Mas caso você comece a adicionar mais níveis ou alterar o nome, essa é, novamente, uma maneira agradável, dinâmica e reutilizável de implementar Então, uma vez que tenhamos isso, vamos extrair daqui, e vamos pesquisar o nível de carga da função, e vamos procurar a função aberta. Pode ver a opção aqui, abrir nível por nome. Agora, obtemos duas variáveis ligeiramente diferentes, então temos o nome do nível atual retornado como uma string e temos o nível de carga retornado que deve ser inserido como uma variável de nome. Perfeitamente bem. Novamente, podemos simplesmente conectá-los. Ambos são um tipo de texto, essencialmente, e o irreal fará essa conversão para nós Então, isso pegará o nome atual do nível em que estamos principais e abrirá o nível com o mesmo nome. Então, estamos apenas reiniciando nossa direita, o outro problema que acabei de perceber aqui é que não temos como sair do jogo Algo que eu realmente estou tentando ajudar aqui é não fazer com que pareça um jogo completo para iniciantes ao final desse processo Uma coisa que descobri ao testar e demonstrar jogos de novos desenvolvedores é que você geralmente fica preso no jogo deles e precisa pressionar F para fechar o painel Portanto, enquanto analisamos a entrada, também podemos nos livrar desse problema O que vou fazer é duplicar a reinicialização do sublinhado do IA Vou renomear este para sair. Dentro do sublinhado principal do IMC, queremos apenas adicionar um novo Então, sabemos que restart é um booleano, uma entrada binária. Portanto, também já saímos do set como booleano digital, o que é perfeito Então, no IMC Underscore main, vamos adicionar um novo Vamos abrir essa opção e selecionar o botão sair. Portanto, para testar no editor, isso é um pouco complicado porque, por padrão, escape é mapeado para finalizar a reprodução Então, se estivéssemos jogando e testando, não conseguiríamos testar. Sem desativar nosso sistema de menu ou nosso botão rápido. Então, eu vou dar isso. Mas se fôssemos empacotar isso e entregá-lo a outra pessoa. Eu quero a chave de escape apenas para fechar o projeto. Não haverá menus, não haverá pop-ups apenas uma maneira rápida de fechar o projeto, então, pelo menos, eu não fico preso depois de construir o projeto. Para testar o editor, o que eu geralmente faço é usar outra encadernação e configurá-la para algo realmente aleatório que, e configurá-la para algo realmente aleatório que outra forma, eu não estaria pressionando na minha jogabilidade. Então, eu posso definir isso como a chave de exclusão. E isso significa que o que eu posso fazer é voltar para minha classe de jogador. Então, vou entrar no núcleo do jogador de avião. E, novamente, estamos nos afastando um pouco das formas ideais de configurar isso agora. Em um projeto real, você provavelmente faria isso dentro de um controlador de player ou em sistemas de menu diferentes, mas não estamos nos aprofundando na criação de sistemas de menu completos. Então, vamos colocar isso em nosso sistema de entrada aqui. Então, temos nosso gráfico de entrada. Ainda estamos mantendo as coisas bem arrumadas, pelo menos Isso ainda está dentro do nosso sublinhado principal do IMC. Isso significa que todas as nossas novas ligações ainda estão sendo E o que podemos fazer é fazer com que o sublinhado do IA seja encerrado. E quando esse botão é pressionado , queremos o evento novamente. E quando esse botão é pressionado, então iniciado, queremos apenas chamar a função embutida, que é sair. Jogo tão rápido. E isso fechará automaticamente a instância do jogo para você. Então, se clicarmos em compilar e salvar, podemos testar isso imediatamente Lembre-se de que no modo play, se eu pressionar Escape, ele teria fechado de qualquer maneira. Então, vou pressionar a tecla delete e a reprodução acabou de Então, isso funcionará para nossa versão empacotada, bem como para nossa versão de editor aqui Portanto, não precisamos fazer mais nada aqui. E eu só queria apresentar a você a funcionalidade rápida, porque, como mencionei, é muito fácil ignorá-la, mas é muito, muito simples de implementar E é apenas uma daquelas coisas que faz seu tipo inicial de sentimento e avaliação de um jogo que você está jogando dê um passo adiante e faça você se sentir como se estivesse jogando um jogo feito por alguém com um pouco mais de experiência fim, queremos que essa interface de usuário apareça quando o jogador morre. Sabemos exatamente quando isso acontece porque temos nossa função de lidar com a morte dentro da classe do jogador. Então, com isso, vamos encontrar nossa função de lidar com a morte. Queremos ir para Override, e queremos encontrar Dyna Queremos ter certeza de que ainda estamos chamando todas essas coisas importantes para pais, para que nosso efeito e tudo mais estejam sendo tratados Mas pouco antes que isso aconteça, ou talvez sim, pouco antes de isso acontecer, porque estamos chamando Destroy na versão principal, queremos aparecer em nossa interface de usuário E podemos fazer isso de forma muito simples, então vamos extrair daqui e encontrar uma função chamada Create Widget Então, essa é uma função para criar um dos nossos widgets de blueprint Podemos inserir isso aqui e queremos encontrar nosso jogo de sublinhados do WBP. Agora, novamente, vou fazer uma pequena observação sobre isso só porque você ficaria surpreso com quantas pessoas esquecem a próxima etapa importante. Parece que isso deveria funcionar. Mas se eu entrar rapidamente e permitir que meu avião seja destruído, chamaremos essa função, forneceremos a ela o widget certo, mas não o veremos na tela Então, novamente, coisa muito comum. Mesmo que pareça que isso é tudo o que precisamos fazer. Na verdade, há uma etapa extra. Queremos retirar esse pino de retorno. Então, isso é criado em segundo plano. Há um widget de fim de jogo que meio que permanece na memória Queremos pegar essa referência e memória e dizer adicionar ao ponto de vista Uma função especial chamada Need to Make aqui, e depois vamos conectar tudo isso. E agora, isso vai realmente funcionar. Então, se entrarmos e apertarmos play novamente, faça com que meus aviões sejam destruídos e pronto. Então isso criou esse menu, mas também o adicionou ao ponto de vista Se eu pressionar R, teremos essa vinculação no menu, então agora também temos uma reinicialização. Assim, podemos entrar e reiniciar o jogo com muita facilidade agora. Vamos acabar com a mesma coisa. E se eu pressionar Delete, algo que eu esqueci lá. Eu ia dizer que, se eu pressionar Delete, posso sair. Não posso porque os jogadores foram destruídos. E lembre-se, nossa obrigação de desistir está no player. Então, talvez queiramos fazer um pouco de duplicação. Vamos encerrar nosso sublinhado IA e a função de encerramento do jogo aqui Não vamos removê-lo aqui. Queremos isso nos dois lugares. Vamos voltar ao fim do jogo, só vamos colar isso aqui. Então, quando o jogador é destruído, ele não existe mais. Obviamente, não podemos sair do jogo. Então, em vez disso, vamos mover essa funcionalidade para o widget GameOver Então, é perfeitamente normal fazer isso. Apenas certifique-se de que o jogador ainda morra. E agora, se eu pressionar delete, podemos fechar o jogo. Então, a mesma funcionalidade, sempre precisamos considerar que, se algo foi completamente removido do jogo, completamente removido da memória, precisamos garantir que todas as funções relevantes ainda estejam disponíveis em outro lugar. E, novamente, se você descobrir, como quando eu estava vendo isso, sinto como se tivéssemos bastante espaço na tela. Então, acho que o que eu poderia fazer são apenas alguns pequenos ajustes para talvez fazer com que isso seja realmente grande, o dobro do tamanho do nosso jogo E então dobre o tamanho da nossa ponta de ferramenta aqui. Portanto, não é nada importante, mas é só voltar, basta preencher um tipo geral de preenchimento e fazer com que tudo pareça o melhor possível, tentando apresentar o jogo da melhor maneira possível. Então, sim, provavelmente há um tipo de estilo geral muito melhor. Pressione para reiniciar, tudo está funcionando. Tão perfeito. Acho que, para um projeto iniciante, um tipo muito simples de remake de algo que existe, mas tentar expandir e melhorar, especialmente a base de código sempre que possível, mas também o feedback geral, o preenchimento e os visuais, será um bom tipo de ponto de aprendizado e um passo na direção certa para Mas isso é basicamente um resumo disso. Então, mais algumas coisas para você aprender nesses pontos de aprendizado. Você pode jogar, atirar em inimigos, ser atingido, morrer, tela de fim de jogo aparece e você pode fazer tudo de novo. Tudo parece muito bom. Temos uma espécie de interface de usuário simples, de aparência moderna e semidesfocada usuário simples, de aparência moderna Você pode pressionar escape ou excluir e fechar o jogo de qualquer lugar. Então, novamente, não estamos fazendo com que pareça um projeto completo de novato em que você está preso e precisa alterar o F quatro do projeto de fim de semana de alguém Então, espero que seja uma boa melhoria em relação ao que você também pode ter visto Portanto, temos um loop de jogo completo. Podemos jogar, morrer, reiniciar e sair. Então, ao longo de todo esse tempo, passamos de um projeto vazio para um jogo completo, movimento com independência de estrutura, projéteis, materiais dinâmicos, inimigos com herança e uma breve visão e uma breve Temos geradores com randomização, garantindo que eles tenham sido criados de forma genérica, mas genéricos de uma forma boa, pois podemos criar a classe uma vez e usá-la para Examinei partículas, áudio, trepidação da câmera, retrocesso e agora a interface Então, espero que essa seja uma boa base. Você pode construir sobre isso. Como mencionei, seria ótimo se você adicionasse alguns inimigos únicos, tentasse dar a eles diferentes padrões de movimento, padrões de armas diferentes, talvez os acelerasse e os tornasse inimigos kamikaze com projéteis conhecidos O que quer que você esteja sentindo sobre suas etapas extras para tornar este projeto único. Traga alguns recursos novos e compartilhe seu progresso e atualizações com outras pessoas. Também poderia adicionar coisas como pontuação, que seria muito fácil de fazer por meio da função de controle compartilhado de morte Sabemos exatamente quando os inimigos estão morrendo, então você pode aproveitar isso e criar algum tipo de sistema de pontuação Então, realmente torne este projeto seu. Pegue referências de outros jogos, veja os exemplos de conteúdo e eu definitivamente recomendo que, neste momento dê uma olhada nos exemplos de conteúdo. Dê uma olhada no mapa de entrada do blueprint e veja exatamente de onde esse projeto foi inspirado e compare o código que você tem com o código desse projeto E, novamente, isso não é para julgar, mas apenas para ver que sempre há maneiras diferentes de abordar um único problema. E veja qual é a sua opinião sobre o que temos em relação ao projeto original. Mas o importante é que agora você criou um jogo, e isso não é nada. Isso é uma conquista, ainda mais se você está dando esses passos extras e realmente sente que está começando a entender pelo menos um pouco do que pode fazer dentro do Unreal Algumas dessas coisas exigirão um pouco de repetição. Talvez você precise voltar e tentar novamente, mas ser capaz de ajustar e implementar esses recursos sozinho é, na verdade, o primeiro grande obstáculo de aprendizado que eu acho que muitas pessoas enfrentam. Então, obrigado por acompanhar com seriedade. Se você chegou até aqui, eu realmente agradeço por dedicar seu tempo a algo que ajudei a criar Mas eu vou e continuo fazendo coisas. Esse é o ponto principal aqui.