Hello,
So I’ve made a raycasting system for my laser guns. I’ve recently inserted a ray-reflection system at end of the function.
Raycasting + server’s visualize:
local RStorage = game.ReplicatedStorage
function castRay(plr: Player, origin: Vector3, dirRaw: CFrame, rFilters: {Instances}, laserProps: {}, canBackfire: boolean)
local cosmets = laserProps["cosmetics"]
local dmeter = cosmets["dmeter"]
local direction = dirRaw.LookVector
direction *= laserProps["range"]
local rParams = RaycastParams.new()
rParams.FilterType = Enum.RaycastFilterType.Exclude
rParams.FilterDescendantsInstances = rFilters
rParams.IgnoreWater = true
local hitReflect = false
local rResult = workspace:Raycast(origin, direction, rParams)
local rayDist
if rResult then
rayDist = rResult.Distance
local hit = rResult.Instance
if hit:GetAttribute("Reflective") then
hitReflect = true
else
searchHumanoidHP(plr, hit, laserProps, true)
cosmets["rayLength"] = rayDist
end
end
------\\ SERVER VISUALIZATION \\---------------------------------------------------------------------------------
local beam = RStorage["LaserBeam"]:Clone()
if rayDist then beam.Size = Vector3.new(dmeter, dmeter, rayDist)
else beam.Size = Vector3.new(dmeter, dmeter, cosmets.rayLength) end
if rayDist then beam.CFrame = CFrame.lookAt(origin, origin + direction) * CFrame.new(0, 0, -rayDist/2)
else beam.CFrame = CFrame.lookAt(origin, origin + direction) * CFrame.new(0, 0, -beam.Size.Z/2) end
beam.Parent = workspace.MouseIgnore
Debris:AddItem(beam, 5)
------\\ SERVER TO CLIENT \\---------------------------------------------------------------------------------------
RStorage.BeamReplicate:FireAllClients(dirRaw, cosmets) -- Send to client to replicate.
-------\\ RAY REFLECTION \\-----------------------------------------------------------------------------------------
if hitReflect == true then
laserProps["range"] -= rayDist
if laserProps["range"] <= 0 then return end
cosmets["rayLength"] = laserProps["range"]
-- Formula: r = d - 2(d ⋅ n)n
-- Code: r = d - (2 * d:Dot(n) * n)
local newOrigin = rResult.Position
local rNormal = rResult.Normal
local reflectNormal = direction - (2 * direction:Dot(rNormal) * rNormal)
local reflectCF = CFrame.lookAt(newOrigin, rResult.Position + reflectNormal)
castRay(plr, newOrigin, reflectCF, {}, laserProps, true)
end
end
The ray-reflection only applies if the hit part has the attribute "Reflective"
, and will recall the function over and over again to reflect as long as it has the said attribute.
Client’s visualization:
RStorage.BeamReplicate.OnClientEvent:Connect(function(cF, cosmets)
local dmeter = cosmets["dmeter"]
local rayLength = cosmets["rayLength"]
local laser = RStorage["LaserBeam"]:Clone()
laser.Size = Vector3.new(dmeter, dmeter, rayLength)
laser.CFrame = cF * CFrame.new(0, 0, -rayLength/2)
laser.Parent = workspace.MouseIgnore
Debris:AddItem(laser, 0.5)
end)
The SERVER VISUALIZATION
thread and client’s version is not far so different.
Issue
The main issue here is with visualizing the raycast when it reflects. I use this part called “LaserBeam” from the ReplicatedStorage. The Z-axis of the size is derived from the rayDist
, if not, then the rayLength
.
There are 3 variables that are used for the Z-axis:
-
laserProps["range"]
→ Basically max distance of the laser/raycast. -
laserProps.cosmets["rayLength"]
→ The one used for the client-sided visualization. -
rayDist
→ Derived fromrResult
(RaycastResult).
Here is a drawing of the visualization results:
Hitting more Attribute"Reflective"
parts:
The LaserBeam(s) seems to position their start point on their previous hit position, but their size seems to exceed the rayDist
?
And lasst problem here is, I’ve messed tzoo much with positioning these lines of codes and my brain is having a blackout.
Feedbacks are wanted. Ask me if there’s some I did not explain.
Here’s the reflection formula I got from:
Thank you for reading