How do I loop casting a ray?

How do I loop casting a ray? I’m trying to loop a ray every second such that it can detect object that appears on the ray path while the object it moving.

What I want to achieve is:
When a player fires the gun, it will create a Bullet Part, the part will tween to where the user pointed at by using Raycasting and TweenService.
It will cast a ray and move the bullet to the shot direction every second.

I modified the code “Making a laser gun” from the Developer Hub for testing so far.
I also use TweenService to move the bullet part.

	local beam = Instance.new("Part", workspace)
	beam.BrickColor = BrickColor.new("Bright red")
	beam.FormFactor = "Custom"
	beam.Material = "Neon"
	beam.Transparency = 0.25
	beam.Anchored = true
	beam.Locked = true
	beam.CanCollide = false
	beam.CFrame = CFrame.new(handle.CFrame.p - beam.CFrame.p)
	local dir = mouse.Hit.p
	
	delay(0,function()
	while true do 
	
	local ray = Ray.new(beam.CFrame.p, dir*1)
	local part, pos = workspace:FindPartOnRay(ray, player.Character, false, true)

	local distance = (tool.Handle.CFrame.p - pos).magnitude
	beam.Size = Vector3.new(0.3, 0.3, 2)
	beam.CFrame = CFrame.new(beam.CFrame.p, pos)
	
	local ti = TweenInfo.new(
		distance * 0.05,
		Enum.EasingStyle.Linear,
		Enum.EasingDirection.Out,
		0,
		false,
		0)
	
	local goal = {
		Position = pos
	}
	
	local tween = tweenser:Create(beam, ti, goal)
  	tween:Play()

	if part ~= nil then
		break
	end

	wait(1)
	end
end)

This shooting direction is not accurate probably due to the variables stacking, but I just feel like there’s a better way to improve the entire code this looks like that it’s a “hacky” way to perform it, any thoughts?

I think the best thing to do would be to have the raycasting as a seperate loop.
I think you should do something like this (assuming you’re on a serverscript)

local Con

Con = RunService.Heartbeat:Connect(function()
     if goalreachedsomethingsomething then
          Con:Disconnect()
          return
     end
     --shoot ray functions thing
end)

local previousPos = startPosition
RunService.Heartbeat:Connect(function()
–ray from previousPos to the current position
–if hit check distance
–if distance is too far, loop again, else disconnect
end)

4 Likes

I think I kinda solved it, however how do I replicate this to the server and such that it will be visible to others?
Firing the RemoteEvent 60 times a second doesn’t seems to be a right way.

		delay(0,function()
		local dir = (mouse.Hit.p - beam.CFrame.p).unit
		
	
		local runService = game:GetService('RunService')
		local Stepped
			Stepped = runService.Stepped:Connect(function()
				local ray = Ray.new(beam.CFrame.p, dir*1)
				local part, pos = workspace:FindPartOnRay(ray, player.Character, false, true)
		 		local dis = (beam.CFrame.p - pos).magnitude

				beam.Size = Vector3.new(0.3, 0.3, 2)
				beam.CFrame = CFrame.new(beam.CFrame.p, pos)
				
				local ti = TweenInfo.new(
					dis * 7/100,
					Enum.EasingStyle.Linear,
					Enum.EasingDirection.Out,
					0,
					false,
					0)
				
				local goal = {
					Position = pos
				}
				
				local tween = tweenser:Create(beam, ti, goal)
			  	tween:Play()
			
			game.ReplicatedStorage.RemoteEvent:FireServer(dis*7/100, pos)
			
				if part ~= nil then
					Stepped:Disconnect()
					if part.Parent:FindFirstChild("Humanoid") then
						part.Parent.Humanoid:TakeDamage(10)
					end
					game:GetService("Debris"):AddItem(beam,1)
				end
			wait()
		end)
	end)

In my another game, I only use TweenService to tween the bullet, I use remote event to fire the server including the details of the bullet part, such as CFrame, ending point etc. However for this one, the ending point is different every second, how do I handle it for this one?

Just fire the remote when it hits something.

Yes, firing a remote 60/s is the wrong way to go about pretty much anything.