“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
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.
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;
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