Optimizing a raycast

Hey, I am making a wizard wand shooting thing.

Anyways, its a script that fires a projectile from one place to another using ray casting. This is a highly modified version of a script I got from a guy on the forum.

Anyway, I feel like some of the parts are useless or that there are better ways (or is it as good as it can be)

Here is the code: (it shoots from 1 part to another part.)

while true do
	--Raycast
	local function rayCast()

	
	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.new("New Yeller")
	laser.Anchored = true
	laser.CanCollide = false
	laser.Locked = true
	laser.CFrame = game.Workspace.Part.CFrame
	laser.Parent = game.Workspace
	laser.Material = "Neon"
	
	local maxDistance =  200
	local curDistance = 0
	
	local stepDistance = 30
	local stepWait = 0
	
	local currentPos = game.Workspace.Part.Position
currentNormal = (game.Workspace.Part2.Position - currentPos).Unit
	
	local function Step(overrideDistance)
		

		-- Cast ray:
		local ray = Ray.new(currentPos, currentNormal * (overrideDistance or stepDistance),true, true)
		local hit, pos, norm = game.Workspace:FindPartOnRayWithIgnoreList(ray, {script.Parent})
		print(pos)
		-- Update laser position:
		laser.Size = Vector3.new(0.001, 0.001, (pos - currentPos).magnitude) --or do 10 studs on the last argument
		laser.CFrame = CFrame.new(currentPos:lerp(pos, 0.5), pos)
		
		local oldPos = currentPos
		currentPos = pos
		
		if (hit) then
		if game.Workspace.Part2 ~= nil and game.Workspace.Part2.Parent ~= nil then
	
		if game.Workspace.Part2.Parent:FindFirstChild("Humanoid")then
		local targetPlayer = game.Workspace.Part2.Parent
		local targetHumanoid = targetPlayer.Humanoid
	
		laser:Destroy()
	
		end
		end
		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()

	laser:Destroy()
	
	end
	
	rayCast()
wait(1)
end

And also, if anyone has a good resource on learning ray casts that would be great. This article from roblox is trash: Raycasting | Documentation - Roblox Creator Hub (in my opinion)

There’s a few details I’d change


Fix bug

This won’t work. It will error if Part2 doesn’t exist. If you try print(game.somethingsomething) you’ll get an error somethingsomething is not a valid member of DataModel “Place1”. You have to use FindFirstChild. The second part of the check is also pointless. If you got Part2 by going through its Parent, then its Parent necessarily has to exist, so there’s no point checking. Here’s the fixed LoC:

if game.Workspace:FindFirstChild("Part2") ~= nil then´


Simplify

I would turn this (indented properly) ...
if hit then
	if game.Workspace:FindFirstChild("Part2") ~= nil then
		if game.Workspace.Part2.Parent:FindFirstChild("Humanoid") then
			local targetPlayer = game.Workspace.Part2.Parent
			local targetHumanoid = targetPlayer.Humanoid

			laser:Destroy()
		end
	end
end
... into this:
if hit then
	local part_2 = game.Workspace:FindFirstChild("Part2")
	local target_character = part_2 and part_2.Parent or nil
	local target_humanoid = target_character and target_character:FindFirstChild("Humanoid") or nil

	if target_humanoid then
		laser:Destroy()
	end
end

It does the same thing but in a manner that I think looks a lot cleaner, with fewer indents, and doesn’t have the two assignments that are never used. I can’t figure out what it’s supposed to do or why it looks for a Humanoid tho :man_shrugging:


Other than that, I believe you can improve performance quite a lot by using a whitelist instead of a blacklist, especially if you can have relatively few parts in the whitelist. But it may not be worth it in your case because you’re doing so many small ray casts instead of a single long one. I wouldn’t worry about the performance of this before it actually becomes an issue.