Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Game Art Effects
Gamedevelopment

Como gerar efeitos incríveis de relâmpagos 2D com Unity (C#)

by
Difficulty:IntermediateLength:LongLanguages:

Portuguese (Português) translation by Jonathan Ramos (you can also view the original English article)

Há muitos usos para efeitos de relâmpagos em jogos, de ambiente de fundo durante uma tempestade até ataques devastadores de um feiticeiro. Neste tutorial, vou explicar como programaticamente gerar efeitos de relâmpago incríveis em 2D: raios, ramos e até mesmo texto.

Este tutorial é escrito especificamente para Unity, com todos os trechos de código em C#. O mesmo tutorial também está disponível com o código JavaScript. Se você não usa Unity, dê uma olhada nesta versão de plataforma agnóstica do mesmo tutorial; é escrito para XNA, mas você deve ser capaz de usar as mesmas técnicas e conceitos em qualquer plataforma e motor de desenvolvimento.

Demonstração

Confira a demonstração abaixo:

Clique no objeto Unity, e em seguida, use as teclas para alternar entre as demonstrações. Algumas demonstrações exigem que você clique em um ou dois locais para ativá-las.

Configuração básica

Para começar, você precisará criar um novo projeto 2D na Unity. O nome que você quiser. Na Unity, crie quatro pastas: Materials, Prefabs, Scripts, e Sprites.

Em seguida, clique na Câmera Principal e certifique-se de que a Projeção está definida como Orthographic. Defina o tamanho da câmera para 10.

Clique com o botão direito do mouse na pasta Materials e selecione Create > Material. Renomeie para Additive. Selecione este material e altere o seu Shader para Particles > Additive. Mais tarde, isso ajudará no "pop" do relâmpago.

Passo 1: Desenhe uma linha brilhante

O bloco de construção básico que precisamos para ter um relâmpago é um segmento de linha. Comece abrindo o seu software de edição de imagem favorito e desenhe uma linha reta de relâmpago com um efeito de brilho. A minha ficou assim:

Queremos desenhar linhas de comprimentos diferentes, então vamos cortar o segmento em três partes como mostrado abaixo (corte a sua imagem, se necessário). Isso nos permitirá esticar o segmento do meio para obter qualquer tamanho. Como nós vamos esticar o segmento do meio, podemos salvá-lo com apenas um único pixel de espessura. Além disso, como os pedaços da direita e da esquerda são imagens espelhadas, só precisamos salvar um deles. Podemos virar o pedaço com o seguinte código.

Arraste seus arquivos de imagem para a pasta Sprites no painel do projeto. Isto irá importar os arquivos para o projeto Unity. Clique sobre os sprites para visualizá-las no painel Inspector. Certifique-se que o tipo de textura está definido como Sprite(2D \ uGUI) e defina a tag como Line.

A tag ajudará a Unity a economizar chamadas para desenhar o nosso relâmpago, então certifique-se de dar a mesma tag aos dois sprites, ou a performance será reduzida.

Agora, vamos declarar uma nova classe para lidar com o desenho do segmento da linha:

A e B são os pontos de extremidade da linha. Ao dimensionar e girar os pedaços, podemos traçar uma linha de qualquer espessura, comprimento e orientação.

Adicione o seguinte método Draw() no fim da classe Line:


A maneira que posicionamos o pedaço do meio e as pontas fará que eles unam-se perfeitamente quando forem desenhados. A primeira ponta é posicionada no ponto A, o meio é esticado para a largura desejada e a ponta final é rotacionada em 180° para desenhar o ponto B.

Agora precisamos criar um prefab para nossa classe Line trabalhar com ele. Na Unity, no menu, selecione GameObject > Create Empty. O objeto aparecerá no seu painel Hierarchy. Renomeie-o para Line e arraste seu script Line para ele. Isso deve ficar conforme a imagem abaixo.

Nós vamos usar esse objeto como um container para as peças de nosso segmento de linha.

Agora precisamos criar objetos para as partes do nosso segmento. Crie três Sprites selecionando GameObject > Create Other > Sprite no menu. Renomeie-os para StartCap, MiddleSegment e EndCap. Arraste-os para nosso objeto Line, para que eles se tornem seus filhos — isso deve ficar como na imagem abaixo.

Vá em cada filho e ajuste seu Material no Sprite Renderer para o material Additive que criamos anteriormente. Atribua a cada um o sprite apropriado. (As duas pontas devem pegar o sprite de ponta e o segmento do meio deve ter o sprite da linha).

Clique sobre o objeto Line para que você possa ver o script no painel Inspector. Coloque os filhos nos encaixes apropriados e arraste o objeto Line para a pasta Prefabs para criar um objeto pré-fabricado. Agora, você pode excluir o objeto Line do painel Hierarchy.

Passo 2: Criar linhas irregulares

Relâmpagos tendem a formar linhas irregulares, então vamos precisar de um algoritmo para gerar estas. Nós faremos isto escolhendo pontos aleatoriamente ao longo de uma linha e deslocando-os com uma distância aleatória.

Usar um deslocamento completamente aleatório tende a fazer a linha muito irregular, então nós vamos suavizar os resultados limitando quão longe os pontos vão ser deslocados de seus vizinhos — veja a diferença entre a segunda e terceira linha na figura abaixo.

Podemos suavizar a linha colocando pontos em um deslocamento similar ao ponto anterior. Isso permitirá que a linha como um todo vague para cima e para baixo, enquanto prevê que qualquer parte fique muito irregular.

Vamos criar uma classe LightningBolt para manipular a criação das nossas linhas irregulares.

O código pode ser um pouco intimidante, mas não é tão ruim depois que você entender a lógica. Antes de continuarmos, entenda que nós escolhemos juntar nossos segmentos no raio (já que instanciar e destruir objetos constantemente pode pesado para a Unity).

  • A função Initialize() será chamada uma vez em cada relâmpago e determinará quantos segmentos de linha que cada raio poderá usar.
  • A função activateLine() irá ativar um segmento usando os dados de determinada posição.
  • A função DeactivateSegments() irá desativar quaisquer segmentos de linha ativa em nosso raio.
  • A função ActivateBolt() irá lidar com criação de nossas linhas irregulares e irá chamar a função activateLine() para ativar nossos segmentos nas posições adequadas.

Para criar as nossas linhas irregulares, começamos calculando o declive entre nossos dois pontos, bem como o vetor normal a essa inclinação. Em seguida, escolhemos um número de posições aleatórias ao longo da linha e armazenamos em nossa lista de posições. Nós escalamos essas posições entre 0 e 1, tal que 0 representa o início da linha e 1 representa o ponto final. Em seguida classificamos essas posições para permitir que sejam facilmente adicionados segmentos entre eles.

O loop atravessa os pontos escolhidos aleatoriamente e desloca-os ao longo do normal por um valor aleatório. O fator de escala está lá para evitar ângulos muito agudos, e o envelope garante que o relâmpago realmente vai para o ponto de destino, limitando o deslocamento quando estamos perto do fim. O spread é para ajudar no controle de quanto os segmentos afastam-se da inclinação da nossa linha; um spread de 0 essencialmente lhe dará uma linha reta.

Então, como fizemos com a nossa classe Line, vamos fazer um prefab. No menu, selecione GameObject > Create Empty. O objeto aparecerá no seu painel Hierarchy. Renomeie-o para Bolt e arraste uma cópia do script LightningBolt para ele. Finalmente, clique no objeto Bolt e atribua o prefab Line, da pasta Prefabs, para o encaixe adequado do script LightningBolt. Quando terminar, simplesmente arraste o objeto Bolt para a pasta Prefabs para criar uma prefab.

Passo 3: Adicionar animação

O relâmpago deve brilhar forte e depois desaparecer. É para isso que temos nossa funções Update() e Draw() no LightningBolt. Chamar o Update() fará com que o relâmpago desapareça. Chamar o Draw() irá atualizar a cor do raio na tela. IsComplete lhe dirá quando o relâmpago desapareceu totalmente.

Passo 4: Criar um relâmpago

Agora que temos nossa classe LightningBolt, vamos de fato usá-la e montar uma cena de demonstração rápida.

Vamos usar um objeto pool para esta demonstração, então vamos criar um objeto vazio para manter nossos raios ativos e inativos (simplesmente para fins organizacionais). Na Unity, no menu, selecione GameObject > Create Empty. O objeto aparecerá no seu painel Hierarchy. Renomeie-o para LightningPoolHolder.

Clique com o botão direito na pasta Scripts e selecione Create > C# Script nomeie seu script para DemoScript e abra-o. Aqui está um código rápido para você começar:

Tudo o que este código faz é nos dar uma maneira de criar os raios usando o objetos pool. Há outras maneiras que você pode configurar isso, mas essa é a que vamos usar! Uma vez criado, tudo o que você vai ter que fazer é clicar duas vezes para criar um raio na tela: uma vez para a posição inicial e outra vez para a posição final.

Vamos precisar de um objeto para colocar nosso DemoScript. No menu, selecione GameObject > Create Empty. O objeto aparecerá no seu painel Hierarchy. Renomeie-o para DemoScript e arraste seu script DemoScript para ele. Clique no objeto DemoScript para podermos vê-lo no painel Inspector. Atribua o prefab Bolt, da pasta Prefabs, ao encaixe correspondente no DemoScript.

Isso deve ser o suficiente para seguir! Execute a cena na Unity unidade e experimente!

Passo 5: Criar os ramos do relâmpago

Você pode usar a classe LightningBolt como um bloco de construção para criar efeitos de relâmpago mais interessantes. Por exemplo, você pode fazer o ramo do relâmpago conforme mostrado abaixo:

Para fazer o ramo do relâmpago, escolhemos pontos aleatórios ao longo dele e adicionamos novos relâmpagos que se ramificam para fora desses pontos. No código abaixo, criamos entre três e seis ramos que separam o relâmpago principal em ângulos de 30°.

Esse código funciona de forma muito semelhante a nossa classe LightningBolt com a exceção de que ele não usa objetos pool. Chamar Initialize() é tudo o que você precisará fazer para criar uma ramificação. Depois disso, você só precisará chamar Update() e Draw(). Eu vou te mostrar exatamente como fazer isso no nosso DemoScript mais adiante no tutorial.

Você deve ter notado a referência a uma função GetPoint() na classe LightningBolt. Nós na verdade ainda não implementamos essa função ainda, então vamos tratar disso agora.

Adicione a seguinte função no final da classe LightningBolt:

Passo 6: Criar o texto de relâmpago

Abaixo está um vídeo de outro efeito que você pode fazer com os relâmpagos:

Nós precisamos fazer mais algumas instalações para este. Primeiro, no painel Project, selecione Create > RenderTexture. Renomeie-o para RenderText e defina seu tamanho para 256x256px. (Não necessariamente precisa ser esse tamanho exato, mas quanto menor for, mais rápido o programa será executado).

No menu, selecione Edit > Project Setting > Tags and Layers. Em seguida, no painel Inspector, expanda Layers para adicionar o Text na opção User Layer 8.

Então precisaremos criar uma segunda câmera. No menu, selecione GameObject > Create Other > Camera. Renomeie para TextCamera e defina a projeção para Orthographic e Clear Flags para Solid Color. Defina o seu Background para (R: 0, G: 0, B: 0, A: 0) e a Culling Mask para apenas ser Text (a camada que acabamos de criar). Finalmente, defina o Target Texture como RenderText (o RenderTexture que criamos anteriormente). Você provavelmente precisará brincar com tamanho da câmera mais tarde, a fim de que tudo caiba na tela.

Agora precisaremos criar o texto que vai ser desenhado com o nosso raio. No menu selecione GameObject > Create Other > GUI Text. Selecione o objeto de texto GUI no painel Hierarchy e escreva no campo Text LIGHTNING, defina Anchor como middle center, e Alignment como center. Em seguida, defina o Layer da camada Text que criamos anteriormente. Você provavelmente vai ter que brincar com a propriedade Font Size para ajustar o texto na tela.

Agora selecione a câmera principal e defina o Culling Mask para ver tudo, menos nossa camada de texto. Isso fará com que nosso texto GUI aparentemente desapareça da tela, mas ele deve ser desenhado no RenderTexture que criamos anteriormente: selecione RenderText do painel Project e você deve ser capaz de ver a palavra Lightning no preview na parte inferior do painel.

Se não consegue ver a palavra LIGHTNING, você precisará brincar com seu posicionamento, tamanho da fonte e tamanho da câmera. Para ajudá-lo a posicionar seu texto, clique em TextCamera no painel Hierarchy e defina o Target Texture para None. Agora você será capaz de ver seu texto GUI se centralizá-lo sobre o TextCamera. Depois de ter tudo posicionado, defina o Target Texture da TextCamera de volta para RenderText.

Agora para o código! Nós necessitaremos obter os pixels do texto que estamos desenhando. Podemos fazer isso desenhando o nosso texto para um RenderTarget e voltando a leitura dos dados do pixel em um Texture2D com Texture2D.ReadPixels(). Então, podemos armazenar as coordenadas dos pixels do texto como um List<Vector2>.

Aqui está o código para fazer isso:

Nota: nós teremos que executar essa função como um Coroutine no início do nosso programa para que ele execute corretamente.

Depois disso, em cada quadro, podemos escolher aleatoriamente pares destes pontos e criar um relâmpago entre eles. Nós queremos que quanto mais perto estiverem os dois pontos, maior seja a chance de nós criarmos um relâmpago entre eles.

Há uma técnica simples que podemos usar para realizar essa tarefa: vamos escolher aleatoriamente o primeiro ponto, e então vamos pegar um número fixo de outros pontos aleatoriamente e escolher o mais próximo.

Aqui está o código para isso (nós vamos adicioná-lo ao nosso DemoScript mais tarde):

O número de pontos candidatos que testamos afetará a aparência do texto relâmpago; a verificação de um maior número de pontos nos permitirá encontrar pontos muito próximos para desenhar relâmpagos entre eles, o que tornará o texto muito limpo e legível, mas com relâmpagos mais curtos entre as letras. Números menores farão o texto do relâmpago parecer selvagem mas menos legível.

Passo 7: Tentar outras variações

Já discutimos sobre ramificar relâmpagos e adicionar relâmpago em textos, mas certamente não são os únicos efeitos que você pode fazer. Vamos olhar algumas outras variações de relâmpagos que você pode querer usar.

Movendo um relâmpago

Você muitas vezes pode querer fazer um relâmpago em movimento. Você pode fazer isso adicionando um novo relâmpago curto a cada quadro no ponto final do relâmpago do quadro anterior.

Raio de explosão

Esta variação oferece um efeito dramático que dispara relâmpagos em um círculo a partir de um ponto:

Passo 8: Juntar tudo no DemoScript

Você vai querer experimentar todos estes efeitos extravagantes que criamos até agora, então vamos colocar todos eles no DemoScript que fizemos anteriormente. Você será capaz de alternar entre os efeitos usando as teclas numéricas do teclado para selecionar o efeito, e então clicando duas vezes, como fizemos com os anteriores.

Aqui está o código completo:

Conclusão

O relâmpago é um grande efeito especial para enfeitar seus jogos. Os efeitos descritos neste tutorial são um bom ponto de partida, mas certamente não é tudo o que você pode fazer com eles. Com um pouco de imaginação, você pode fazer todos os tipos de efeitos de relâmpago que imaginar! Baixe o código fonte e experimente por conta própria.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.