Bullet hit sparks

Hello!

I’ve used the FastCast module for projectiles in my game, and currently i’m trying to get impact effects working in the game:

“Sparks” (poor wording)

“Reflected” particles (poor wording again, basically having particles go in one direction based on the wall they hit on and it’s rotation instead of all directions)

However i have no experience with creating reflected projectiles, or “reflected” particles.
I’ve seen this following post:


but i don’t know how to combine local reflectedNormal = normal - (2 * normal:Dot(surfaceNormal) * surfaceNormal) with whatever ““spark”” physics you can get, getting them to bounce after a shot, or just having debris shoot out in a direction that lines up with the angle of the wall or player it got shot on. This means i need to figure out how to use normals (the argument given by default rays and FastCast) ((basic knowledge?)), and how i can use them.

PS. If the wording is confusing, it’s because of my poor choice of words. sorry in advance.

*Edit 1: added second video and descriptions for both

3 Likes

I think you’re a little confused by what Crazyman is explaining in that tutorial.

If you look at the video that you posted of Phantom Forces, the sparks aren’t really getting “reflected” like a mirror, they’re simply bouncing off at a nearly orthogonal direction to the hit basepart. You can get the orthogonal vector to a basepart based on the raycast’s “normal” when you hit the basepart.

My guess is that the math for generating sparks is probably something like this:

local hitPart, hitPos, normal = workspace:FindPartOnRay(whatever)

local sparkDirection = normal + Vector3.new(math.random(-10, 10)/10, math.random(-10, 10)/10, math.random(-10,10)/10

To generate the spark from there, you can either use a part with a trail (which is probably inefficient), a particle emitter, or something else… which I’m not sure, but that’s not related to this post.

1 Like

Great to know all of that. I will attempt to mess with that soon enough.

1 Like

After a bit of playing, i managed to create something simple like this:

The code is really simple too;

function OnRayHit(HitPart, HitPoint, Normal, Material, CosmeticBulletObject)
		
		local part = CosmeticBulletObject:Clone()
		local equasion = (Vector3.new(Normal.Y * 90,Normal.X * 90,Normal.Z * 90)) --bad way to say it lmao, basically normal with fixed faces
		
		part.CFrame = CFrame.new(HitPoint,equasion)
		part.Orientation = equasion
		
		local CurrentNormal = part.CFrame.LookVector 
		
		part:Destroy()
		CosmeticBulletObject:Destroy()
		
		for i = 1,RNG:NextNumber(3,5) do
			local spark = game.ReplicatedStorage.Spark:Clone()
			local reflect = equasion + Vector3.new(math.random(-2, 2)/2, math.random(-2, 2)/2, math.random(-2,2)/2) * 45
			
			spark.Parent = Viewmodel
			
			spark.Position = HitPoint
			spark.CFrame = spark.CFrame:ToWorldSpace(CFrame.new(0,0,0))
			spark.Orientation = reflect
			
			spawn(function()
				game:GetService("RunService").RenderStepped:Wait()
				spark:Destroy()
			end)
		
		end
	end

This means i could simply create a particle emitter for each material/surface type and angle the spark parts against the wall then enable the particle emitter (as i finally figured out how normals work), But fixing
this current script would also provide a good effect. I’ve chosen to have everything disappear after a frame due to my lack of physics knowledge. This being said, i have 2 issues with it;

-the part of the “”"""""""“spark”""""’" is visible on the other side of the wall
-they’re grouped together instead of looking like they’re going off of the hitpoint

This means i need to figure out how to offset them from the point. i tried doing it with spark.CFrame = spark.CFrame:ToWorldSpace(CFrame.new(0,0,0)) but entering anything into the cframe arguments simply offsets the sparks up or to the sides, basically;

You need to use HitPoint and direction to get the look vector and then move alongside it.

I almost got it figured out - given i do some additional configuration, there’s one thing left:

If i fire in a positive X or positive Z direction, the sparks appear correctly. However, If i fire from a negative X/Z direction onto a wall, the sparks appear on the other side of the wall. I’m guessing this has to do with multiplying the normals etc. but i still have little idea what’s wrong. Here’s the updated code, if anyone cares:

	function OnRayHit(HitPart, HitPoint, Normal, Material, CosmeticBulletObject)
			
			local part = CosmeticBulletObject:Clone()
			local equasion = (Vector3.new(Normal.Y * 90,Normal.X * 90,Normal.Z * 90)) --bad way to say it lmao, basically normal with fixed faces
			
			part.CFrame = CFrame.new(HitPoint,equasion)
			part.Orientation = equasion
			
			local CurrentNormal = part.CFrame.LookVector 
			
			part:Destroy()
			CosmeticBulletObject:Destroy()
			
			for i = 1,RNG:NextNumber(3,5) do
				local spark = game.ReplicatedStorage.Spark:Clone()
				local pointer = game.ReplicatedStorage.Pointer:Clone()
				local reflect = equasion + Vector3.new(math.random(-2, 2)/2, math.random(-2, 2)/2, math.random(-2,2)/2) * 45
				
				pointer.Parent = Viewmodel
				spark.Parent = pointer
				
				pointer.Position = HitPoint
				pointer.Orientation = reflect
				
				spawn(function()
					for i = 1,5 do
						spark.CFrame = pointer.CFrame:ToWorldSpace(CFrame.new(0,0,i))
						spark.Transparency = spark.Transparency + 0.4
						game:GetService("RunService").RenderStepped:Wait()
					end
					game:GetService("RunService").RenderStepped:Wait()
					spark:Destroy()
				end)
			
			end
	end