Hello Developers,
I’m currently trying to develop reflective rays to create the illusion of Rays “bouncing off” a disco ball.
However, my partner @xM_ighty and I cannot seem to find a solution for ray casting. We have had multiple attempts.
Here is our closest we’ve ever gotten with raycasting.
Here is another attempt:
local Part = Instance.new("Part")
Part.Name = "Beam"
Part.Transparency = .25
Part.Reflectance = .25
Part.FormFactor = "Custom"
Part.Anchored = true
Part.BrickColor = BrickColor.Red()
Part.Size = Vector3.new(.2, .2, (Current - Ray_Pos).Magnitude)
Part.CFrame = CFrame.new(Current + (Ray_Pos - Current) / 2, Ray_Pos)
Part.Parent = workspace.Ignore
end
function Not_Zero(Value)
local Up = math.ceil(Value + .1)
local Down = math.floor(Value - .1)
if Up ~= 0 and Up ~= -0 then
return Up
elseif Down ~= 0 and Down ~= -0 then
return Down
end
end
Current = Vector3.new(0, 3, 0)
Heading = Vector3.new(0, 0, -1)
Ray_Part, Ray_Pos = workspace:FindPartOnRay(Ray.new(Current, Heading * 900), workspace.Ignore)
if Ray_Part then
Trace_Ray(Ray_Pos)
Current = Ray_Pos
Angle = Ray_Part.CFrame.lookVector
local R_X, R_Z = (Angle.X + Heading.X) / 2, (Angle.Z + Heading.Z) / 2
Heading = Vector3.new(R_X * -Heading.Z, 0, R_Z * -Heading.X).unit
end
repeat
Ray_Part, Ray_Pos = workspace:FindPartOnRay(Ray.new(Current, Heading * 250), workspace.Ignore)
if Ray_Part then
Trace_Ray(Ray_Pos)
Current = Ray_Pos
Angle = Ray_Part.CFrame.lookVector
local R_X, R_Z = (Angle.X + Heading.X) / 2, (Angle.Z + Heading.Z) / 2
Heading = Vector3.new(R_X * -Heading.Z, 0, R_Z * -Heading.X).unit
end
until not Ray_Part or Ray_Part.Name == "Stop"
Trace_Ray(RayPos)
-- Calculate real-time laser reflections!
while wait() do
Current = workspace.Emitter.Position
Heading = workspace.Emitter.CFrame.lookVector
for ,Beam in ipairs(workspace.Ignore:GetChildren())do
Ray_Part, Ray_Pos = workspace:FindPartOnRay(Ray.new(Current, Heading * 900), workspace.Ignore)
if Ray_Part then
Beam.Size = Vector3.new(.2, .2, (Current - Ray_Pos).Magnitude)
Beam.CFrame = CFrame.new(Current + (Ray_Pos - Current) / 2, Ray_Pos)
Current = Ray_Pos - Heading * .1
Angle = Ray_Part.CFrame.lookVector
local R_X, R_Z = (Angle.X + Heading.X) / 2, (Angle.Z + Heading.Z) / 2
Heading = Vector3.new(R_X * -Heading.Z, 0, R_Z * -Heading.X).unit
else
Beam:Destroy()
end
end
Ray_Part, Ray_Pos = workspace:FindPartOnRay(Ray.new(Current, Heading * 900), workspace.Ignore)
if Ray_Part and #workspace.Ignore:GetChildren() < 15 then
Trace_Ray(Ray_Pos)
end
end
Any help would be appreciated. Thank you.
UPDATE:
Thanks for all the great responses, it helped us through the process a little bit. But after a while, we hit a brick wall. Literally and metaphorically. our ray was casted and it did reflect off the wall. The laser ray is casted off the block and reflected off of 2 walls.
But however, when I place a block rotated at 45 degrees, I expected the ray to reflect off the 45 degree wall and in the direction of that wall. But however, this occurs.
No ray is casted, nor reflected.
Here is our script placed within the block:
function Shoot()
local laser = Instance.new("Part")
laser.Name = "Laser"
laser.FormFactor = Enum.FormFactor.Custom
laser.TopSurface, laser.BottomSurface = 0, 0
laser.Size = Vector3.new(0.2, 0.2, 0.2)
laser.BrickColor = BrickColor.Random()
laser.Anchored = true
laser.CanCollide = false
laser.Locked = true
laser.CFrame = script.Parent.CFrame
laser.Parent = game.Workspace
local maxDistance = 50000000
local curDistance = 0
local stepDistance = 500
local stepWait = 0
local currentPos = script.Parent.Position
local currentNormal = script.Parent.CFrame.lookVector
local function Step(overrideDistance)
-- Cast ray:
local ray = Ray.new(currentPos, currentNormal * (overrideDistance or stepDistance))
local hit, pos, norm = game.Workspace:FindPartOnRayWithIgnoreList(ray, {script.Parent})
-- Update laser position:
laser.Size = Vector3.new(0.4, 0.4, (pos - currentPos).magnitude)
laser.CFrame = CFrame.new(currentPos:lerp(pos, 0.5), pos)
local oldPos = currentPos
currentPos = pos
if (hit) then
-- r = d - 2(d DOT n)n
-- Reflect:
local reflect = (currentNormal - (2 * currentNormal:Dot(norm) * norm))
currentNormal = reflect
Step(stepDistance - (pos - oldPos).magnitude)
return
end
curDistance = (curDistance + (pos - oldPos).magnitude)
-- Apply fade effect to laser as it approaches max distance from < 75 studs:
if (curDistance > (maxDistance - 75)) then
local d = (curDistance - (maxDistance - 75)) / 75
laser.Transparency = d
end
-- Recurse if max distance not reached:
if (curDistance < maxDistance) then
wait(stepWait)
Step()
end
end
Step()
end
Shoot()
wait(1)
(Note that I changed the maxDistance
to an exaggerated amount to test the reflection physics. However, it’s not making any sense)
Any thoughts or suggestions?
Thank you.
-Andy