Any way to optimize this Sauron Eye script for less lag?

Not sure if this goes under scripting support or this, but I have this system that is a giant sauron eye, that finds the nearest players and kills them, if it hits a part it will destroy it and explode parts around it, although it is SUPER laggy, I get average 30k ping when restarts, everytime the person it is tracking dies it has to restart, please help me optimize it :slight_smile:

Server script:


local RunService = game:GetService("RunService")

local EyeEventRemote = game:GetService("ReplicatedStorage"):WaitForChild("EyeEvent")

local Eye = game.Workspace.HappyHome.Home.EyeOfSauron.Eye
local Map = game:GetService("Workspace"):FindFirstChild("HappyHome"):Clone()

local Permitted = {101571376}

function FindNearest()
	local ChosenPlayer = nil
	local ChosenDistance = math.huge
	for _,Player in ipairs(game.Players:GetPlayers()) do
		local PrimaryPart = Player.Character and Player.Character.PrimaryPart
		local NewDistance = PrimaryPart and (Eye.Position - PrimaryPart.Position).Magnitude
		if PrimaryPart and ChosenDistance > NewDistance then
			ChosenDistance = NewDistance
			ChosenPlayer = Player
		end
	end
	return ChosenPlayer and ChosenPlayer.Character
end

game.Players.PlayerAdded:Connect(function(player)
	if table.find(Permitted, player.UserId) then
		player.Chatted:Connect(function(msg)
			if msg == "!EyeEvent" then
				
				if game.Workspace.HappyHome then
					MinigameActive = true
				else
					Map:Clone().Parent = workspace
					MinigameActive = true
				end
			elseif msg == "!EndEvent" then
				MinigameActive = false
			elseif msg == "!Reset" then
				workspace.HappyHome:Destroy()
				Map:Clone().Parent = workspace
			end
		end)
	end
end)

local Detector = Instance.new("Part")
Detector.Anchored = true
Detector.CanCollide = false
Detector.Transparency = 0.5
Detector.Color = Color3.fromRGB(255, 0, 0)
Detector.Size = Vector3.new(1, 1, 1) * 4

MinigameActive = false







function startGame()
	

	local Target = FindNearest()

	local TargetPrimaryPart = Target or Target.PrimaryPart

	local laser_Thickness = .5



	local rayOriginPart = Eye
	local rayTargetPart = Target.HumanoidRootPart


	local RayCastParameters = RaycastParams.new()
	RayCastParameters.FilterDescendantsInstances = Eye.Parent:GetChildren()
	RayCastParameters.FilterType = Enum.RaycastFilterType.Blacklist

	local results

	--local rayTargetPart = rootPart
	local function castRay()
		local origin = rayOriginPart.CFrame.Position
		local rayTarget = rayTargetPart.CFrame.Position
		local direction = (rayTarget - origin)

		results = workspace:Raycast(origin, direction, RayCastParameters)

		if not results then
			results = {Position = rayTarget}
		end

		local distance = (results.Position - origin).Magnitude

		
		game.ReplicatedStorage.EyeEvent:FireAllClients(origin, rayTarget, distance, LaserPart)
	end

	game.ReplicatedStorage.EyeEvent.OnServerEvent:Connect(function(Player, clientResults)

		if clientResults ~= nil and results ~= nil then
			local difference = ((clientResults.Position - results.Position) * Vector3.new(1, 1, 1)).Magnitude

			if difference < 5 then
				
				Player.character.Humanoid:TakeDamage(5)
				task.wait(2)

			end
		end
	end)

	LaserPart.Touched:Connect(function(hit)
		wait(1)
		if hit and hit.Parent and not hit:IsDescendantOf(workspace.HappyHome) and not hit.Parent:IsA("Accessory") or hit:IsA("Accessory") then
			--[[local humanoid = hit.Parent.Humanoid

			humanoid:TakeDamage(5)
			wait(1)]]
			
		elseif hit:IsDescendantOf(workspace.HappyHome) then
			local hitPos = hit.Position	


			hit:Destroy()

			local DetectorCopy = Detector:Clone()
			DetectorCopy.Position = hit.Position
			DetectorCopy.Touched:Connect(function()

			end)
			DetectorCopy.Parent = workspace
			local PartsTouching = DetectorCopy:GetTouchingParts()
			DetectorCopy:Destroy()

			for _, Part in pairs(PartsTouching) do
				if Part:IsDescendantOf(workspace.HappyHome) then
					Part:BreakJoints()
					if Part.Anchored ~= true then
						Part:ApplyImpulse(Vector3.new(math.random(1, 50), math.random(100, 500), math.random(1,50)))
					else
						Part.Anchored = false
						Part:ApplyImpulse(Vector3.new(math.random(1, 50), math.random(100, 500), math.random(1,50)))
					end
					
				end
			end

			--hit:ApplyImpulse(Vector3.new(math.random(1, 50), math.random(-100, 500), math.random(1, 50)))

			--[[local Explosion = Instance.new("Explosion")
				Explosion.DestroyJointRadiusPercent = 0
				Explosion.Position = hitPos
				Explosion.BlastPressure = 10000
				Explosion.BlastRadius = 5
				Explosion.Visible = true
			Explosion.Parent = hit.Parent
			wait(5)
			
			Explosion.Hit:Connect(function(hit, distance)
				local hum = hit.Parent:FindFirstChildOfClass("Humanoid")
				if hum then
					hum:TakeDamage(0)
				else
					hit:BreakJoints()
				end
			end)]]
		end


	end)

	RunService.Stepped:Connect(castRay)
end





while true do
	if MinigameActive == true then
		startGame()
	end
	wait(10)
end

Client:


local RunService = game:GetService("RunService")

local player = game:GetService("Players").LocalPlayer

local RayCastParameters = RaycastParams.new()
RayCastParameters.FilterDescendantsInstances = game.Workspace.HappyHome.Home.EyeOfSauron.Eye.Parent:GetChildren()
RayCastParameters.FilterType = Enum.RaycastFilterType.Blacklist

local LaserPart = Instance.new("Part")
LaserPart.Color = Color3.fromRGB(255, 0, 0)
LaserPart.Anchored = true
LaserPart.CanCollide = false
LaserPart.Parent = workspace

game.ReplicatedStorage.EyeEvent.OnClientEvent:Connect(function(origin, target, distance, LaserPart)
	
	local direction = (target - origin)
	
	
	local results = workspace:Raycast(origin, direction, RayCastParameters)

	if not results then
		results = {Position = target}
	end

	local distance = (results.Position - origin).Magnitude

	
	local laser_Thickness = .5
	
	LaserPart.Size = Vector3.new(
		laser_Thickness,
		laser_Thickness,
		distance
	)

	
	LaserPart.CFrame = CFrame.new(origin, target) * CFrame.new(0,0, -distance / 2)

	local character = player.Character
	
	game.ReplicatedStorage.EyeEvent:FireServer(results)
	
	
end)

thanks so much in advance.

I suggest changing the global functions to local functions to reduce the lag a bit.

local function function()

Also, create some variables for lines that are frequently repeated.

Example:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

Also, don’t use game:GetService(“Workspace”), it’s already in the explorer.

1 Like

if you have spaces after the commas in previous math.random’s then add a space after the comma here

I’d say your lag is due to this:
RunService.Stepped:Connect(castRay)

then that castRay function fires events to all clients every Stepped cycle. Maybe figure out a way to update less frequently and still be useable.

2 Likes

Just so you know, the problem definitely isn’t that he’s not using local functions.
You should always use local variables but not using them doesn’t cause lag

Also, it’s fine to use game:GetService("Workspace") if you want, it doesn’t hurt performance. For most people using workspace is easier and less painful, but if you want to be more consistent then getting workspace is somewhat better.

1 Like

			local DetectorCopy = Detector:Clone()
			DetectorCopy.Position = hit.Position
			DetectorCopy.Touched:Connect(function()

			end)
			DetectorCopy.Parent = workspace

What’s the point of this? Why set up a connect event if it does nothing?

Any ideas, or methods or work arounds?

I’m not sure, can you explain how it works? Why does it fire events to the client and receive events from the clients every frame? What is the purpose of that?

It fires to the client to show the visual effect of the ray cast, and it fires back a result of the ray cast to compare what the client sees then the server, and if it is like 4 blocks it damages them, since it is delays behind them. Shown here: https://gyazo.com/e4799b6a5778d056a766408b464883a0

Edit: it still does delay sadly