[TUTORIAL] Aprenda a criar efeito de raio em seu jogo

E aí, gente :v:! Queria mostrar para vocês como colocar efeito de raio em seu jogo. No meu exemplo, o raio sai do meu personagem e vai até um bloco.

Para fazer esse efeito, usaremos alguns recursos como TweenService, Debris e um pouco de matemática. Então, vamos para ação! :rocket:

1) Criando o bloco que será atingido pelo raio

Dentro de um projeto no Roblox Studio, crie uma parte e adicione um ClickDetector e um Script nele. O ClickDetector permite que nossa Part, chamada aqui de “Bloco”, possa reagir a eventos do mouse que serão programados no Script que está no Bloco. Estrutura:

image

2) Escutando o evento de clique no Script do Bloco

Dentro do Script do Bloco, vamos adicionar o código inicial para escutar os cliques feitos em nosso bloco:

local Bloco = script.Parent
local ClickDetector = Bloco.ClickDetector
ClickDetector.MaxActivationDistance = 100 -- fixando distância máxima em que o clique é permitido
ClickDetector.MouseClick:Connect(function (jogador) -- o roblox nos manda na função qual jogador fez o clique
	print(jogador)
end)

Se você já der play no jogo, vai ver o seu nome aparecendo no output do Roblox Studio. Por enquanto é isso, mas já vamos voltar nesse Script para rodar o efeito de raio dentro desse evento de clique!

3) Criando o código que gera o raio

Vamos isolar o código que cria o raio dentro de um ModuleScript. Isso é bacana por organização de código e também porque você consegue importá-lo em quantos blocos você quiser depois!

No meu exemplo, eu criei um ModuleScript chamado “GeradorDeRaio” e o coloquei no ReplicatedStorage:

image

O nosso GeradorDeRaio terá a seguinte estrutura inicial:

-- Declarando a table que terá a função do raio
local GeradorDeRaio = {}

-- Part que ser usada o efeito do raio. Experimente trocar a cor ou seu tamanho!
local ParticulaDoRaio = Instance.new("Part")
ParticulaDoRaio.BrickColor = BrickColor.new("Electric blue")
ParticulaDoRaio.Material = Enum.Material.Neon
ParticulaDoRaio.CanCollide = false -- para que o raio não empurre você ou o Bloco
ParticulaDoRaio.Anchored = true -- para que o raio fique em posição ao invés de cair

-- Função onde vamos calcular as posições onde as partículas de raio vão aparecer
function GeradorDeRaio.CriarEfeito(PosicaoInicial, PosicaoFinal, NumeroDeParticulas)
end

-- Retornando a table que poderá ser importada em outros scripts
return GeradorDeRaio

A ideia é que a função GeradorDeRaio.CriarEfeito receba a posição de 2 objetos e crie uma linha de um até outro com a ParticulaDoRaio. O NumeroDeParticulas define quantas ParticulaDoRaio serão usadas no caminho entre esses 2 objetos. O retorno dessa função será um Model que terá essa linha de ParticulaDoRaio.

Vamos ver então como a função GeradorDeRaio.CriarEfeito funciona:

-- Dentro da função
local PosicoesDasParticulas = {} -- irá guardar as posições das ParticulaDoRaio
	
	for index = 0, NumeroDeParticulas do
		local Deslocamento = Vector3.new(math.random(-1, 1), math.random(-1, 1), math.random(-1, 1)) -- experimente aumentar ou diminuir os números de random!
		local Distanciamento = (PosicaoFinal - PosicaoInicial).Unit * index
		local PosicaoDaParticula = PosicaoInicial + Distanciamento * (PosicaoFinal - PosicaoInicial).Magnitude / NumeroDeParticulas
		
		-- esse if é para que não haja deslocamento de posição caso seja a primeira ou última partícula de raio, que são onde fica o boneco do jogador e o Bloco
		if index == 0 or index == NumeroDeParticulas then
			Deslocamento = Vector3.new(0, 0, 0)
		end
		
		PosicoesDasParticulas[#PosicoesDasParticulas+ 1] = PosicaoDaParticula + Deslocamento -- experimente não somar o Deslocamento que você vai ver o raio sair como uma linha quase que totalmente reta
	end
  • Definimos uma table Pontos
  • Iteramos de 0 até o valor de NumeroDeParticulas. Eu recomendo vocês experimentarem vários valores na hora de chamar a função para ver a diferença!
  • Declaramos um vetor Deslocamento que serve para adicionar leves distorções na linha entre os 2 objetos. Se você removê-lo, vai ver que o resultado será de uma linha quase reta.
  • Calculamos um Distanciamento onde o index informa quantos “passos” em direção a PosicaoFinal uma das ParticulaDoRaio estará
  • Calculamos a PosicaoDaParticula fazendo uso do Distancimento calculado anteriormente e o NumeroDeParticulas para criar um espaçamento mais uniforme entre as ParticulaDoRaio
  • Por fim, a gente aplica o Deslocamento na posição da partícula

Bastante coisa, né :tired_face:? Mas já estamos terminando com essa parte. Para finalizar, é retornar um Model que contém cada ParticulaDoRaio nas posições que criamos acima:

-- Criando um Model que conterá as partículas de raio e será inserido no workspace
local Model = Instance.new("Model")
Model.Name = "Raio"
Model.Parent = workspace
	
for index = 1, #PosicoesDasParticulas do
	-- como precisamos fazer cálculos que envolvem a posição da próxima partículas, só entrando na condição se existir um próximo valor no PosicoesDasParticulas
	if PosicoesDasParticulas[index + 1] ~= nil then
		local Raio = ParticulaDoRaio:Clone()
		Raio.Size = Vector3.new(0.3, 0.3, (PosicoesDasParticulas[index] - PosicoesDasParticulas[index + 1]).Magnitude) -- experimente alterar os 2 primeiros valores que são os eixos x e y para ver mudança no tamanho
		Raio.CFrame = CFrame.new((PosicoesDasParticulas[index] + PosicoesDasParticulas[index + 1]) / 2, PosicoesDasParticulas[index + 1])
		Raio.Parent = Model
	end
end

return Model

No trecho cima, nós estamos:

  • Criando o Model que guardará cada partícula
  • Iterando sobre cada posição de partícula calculada
  • Criando uma cópia da ParticulaDoRaio com a função Clone
  • Dando um tamanho a essa cópia em que o eixo Z terá o tamanho entre a posição atual e a próxima
  • Criando o CFrame dessa cópia com as posições que a gente calculou
  • Por fim, inserindo a cópia da ParticulaDoRaio no Model e então a retornando

4) Executando o módulo ao clicar no Bloco

Com o nosso GeradorDeRaio está pronto, agora é voltar pro Script do nosso Bloco e fazer dele!

  • No início do Script, vamos pegar referência do TweenService e importar nosso GeradorDeRaio:
local TweenService = game:GetService("TweenService") -- serviço do Roblox para ajudar na animação
local GeradorDeRaio = require(game:GetService("ReplicatedStorage"):WaitForChild("GeradorDeRaio")) -- A gente importa ModuleScript através da função require
  • Depois, dentro da função do ClickDetector, vamos pegar os valores necessários para a função GeradorDeRaio.CriarEfeito que são a posição inicial do jogador, a posição do bloco e quantidade de seções que queremos gerar:
local BonecoDoJogador = jogador.Character or jogador.CharacterAdded:wait()
local PosicaoInicial = BonecoDoJogador.PrimaryPart.Position
local PosicaoFinal = Bloco.Position
local NumeroDeParticulas= 20 -- esse número diz quantas partículas o raio terá. experimente ir alterando esse valor
  • E logo depois, vamos chamar a função para criar o raio!
local Raio = GeradorDeRaio.CriarEfeito(PosicaoInicial, PosicaoFinal, NumeroDeParticulas)

Feito isso, teremos recebido a linha de ParticulaDeRaio que é retornada como Model para a variável Raio. Se vocês rodarem o jogo agora, vão ver que as partículas do nosso raio já estão aparecendo no jogo MAS elas ficam paradas eternamente lá.

O que queremos então é remover o raio após um tempo! Então, vamos pros acabamentos.

5) Toques finais

Para remover o raio é bem simples, é só você destrui-lo! Mas como eu não quero fazer isso de imediato e quero garantir que não tenha erro, eu vou usar o Debris do Roblox:

game:GetService("Debris"):AddItem(Raio, 0.2) -- destruindo o raio após 0.2s

Rode o jogo e você vai ver que agora seu raio está desaparecendo! Como um passo extra, a gente pode usar o TweenService que mencionei algumas vezes. Eu vou usar ele para suavizar o desaparecimento do raio ao animar a transparência das partículas do raio até ficarem invisíveis. Vejamos como é isso:

-- ANTES do Debris, a gente itera cada parte do raio
for _, Particula in pairs(Raio:GetChildren()) do
	local Efeito = TweenService:Create(Particula, TweenInfo.new(0.2, Enum.EasingStyle.Sine), { Transparency = 1 }) -- criando animação de transição para cada Particula
	Efeito:Play() -- executando o efeito da Particula
	Efeito:Destroy() -- removendo efeito após ele ter cima executado
end

A função TweenService:Create recebe 3 valores. A Part que queremos animar, um TweenInfo que diz o tipo de transição que ele vai fazer (veja os tipos de transições em https://developer.roblox.com/en-us/api-reference/enum/EasingStyle), e uma table dizendo que propriedades que vamos modificar na nossa parte. No exemplo acima, eu quero modificar a Transparency de cada Particula até 1 que é quando ela fica invisível.

6) Scripts finalizados

Script do Bloco:

local TweenService = game:GetService("TweenService")
local GeradorDeRaio = require(game:GetService("ReplicatedStorage"):WaitForChild("GeradorDeRaio")) -- A gente importa ModuleScript através da função require
local Bloco = script.Parent
local ClickDetector = Bloco.ClickDetector
ClickDetector.MaxActivationDistance = 100 -- fixando distância máxima em que o clique é permitido
ClickDetector.MouseClick:Connect(function (jogador) -- o roblox nos manda na função qual jogador fez o clique
	print(jogador)
	local BonecoDoJogador = jogador.Character or jogador.CharacterAdded:wait()
	local PosicaoInicial = BonecoDoJogador.PrimaryPart.Position
	local PosicaoFinal = Bloco.Position
	local NumeroDeParticulas = 20 -- esse número diz quantas seções o raio terá. experimente ir alterando esse valor
	local Raio = GeradorDeRaio.CriarEfeito(PosicaoInicial, PosicaoFinal, NumeroDeParticulas)
	for _, Particula in pairs(Raio:GetChildren()) do
		local Efeito = TweenService:Create(Particula, TweenInfo.new(0.2, Enum.EasingStyle.Sine), { Transparency = 1 }) -- criando animação de transição para cada Particula
		Efeito:Play() -- executando o efeito da Particula
		Efeito:Destroy() -- removendo efeito após ele ter cima executado
	end
	game:GetService("Debris"):AddItem(Raio, 0.2) -- destruindo o raio após 0.2s
end)

GeradorDeRaio:

local GeradorDeRaio = {}

local ParticulaDoRaio = Instance.new("Part")
ParticulaDoRaio.BrickColor = BrickColor.new("Electric blue")
ParticulaDoRaio.Material = Enum.Material.Neon
ParticulaDoRaio.CanCollide = false
ParticulaDoRaio.Anchored = true

function GeradorDeRaio.CriarEfeito(PosicaoInicial, PosicaoFinal, NumeroDeParticulas)
	local Pontos = {}
	
	for index = 0, NumeroDeParticulas do
		local Deslocamento = Vector3.new(math.random(-1, 1), math.random(-1, 1), math.random(-1, 1)) -- experimente aumentar ou diminuir os números de random!
		local Distanciamento = (PosicaoFinal - PosicaoInicial).Unit * index
		local PosicaoDoPonto = PosicaoInicial + Distanciamento * (PosicaoFinal - PosicaoInicial).Magnitude / NumeroDeParticulas
		
		-- esse if é para que não haja deslocamento de posição caso seja a primeira ou última partícula de raio, que são onde fica o boneco do jogador e o Bloco
		if index == 0 or index == NumeroDeParticulas then
			Deslocamento = Vector3.new(0, 0, 0)
		end
		
		Pontos[#Pontos + 1] = PosicaoDoPonto + Deslocamento -- experimente não somar o Deslocamento que você vai ver o raio sair como uma linha quase que totalmente reta
	end
	
	local Model = Instance.new("Model")
	Model.Name = "Raio"
	Model.Parent = workspace
	
	for index = 1, #Pontos do
		if Pontos[index + 1] ~= nil then
			local Raio = ParticulaDoRaio:Clone()
			Raio.Size = Vector3.new(0.3, 0.3, (Pontos[index] - Pontos[index + 1]).Magnitude)
			Raio.CFrame = CFrame.new((Pontos[index] + Pontos[index + 1]) / 2, Pontos[index + 1])
			Raio.Parent = Model
		end
	end

	return Model
end

return GeradorDeRaio

Como criar efeito de raio em seu jogo
É isso, pessoal! Agora é usar a criatividade para usar isso em outros contextos. Você poderia adaptar o código para, por exemplo, poder ser usado em outros jogadores ao invés de Parts e dar dano no humanoid do jogador quando ele fosse atingido!

Até a próxima :zap::zap:

4 Curtidas

Show!!! @douglas Mt top!!

1 Curtida

Efeito sem TweenService e Debris. O raio fica permanentemente na tela!
Sem TweenService e Debris

1 Curtida

Ficou meio grande o post kk
Mas no final tem os scripts prontos então fica mais tranquilo para testar

1 Curtida

Fera cara, podia fazer menor mais ainda ta muito bom, testei no meu jogo com UIS e funciono certinho !!!

1 Curtida