Pathfinding server script causing lag

Alright, I’ve been trying to get this code to be more optimized without restarting from scratch.

Basically, code works fine, but due to it being so unoptimized, it slows the server and some other server scripts on my game start slowing down. I have multiple thoughts what would be causing the lag, for example, a path is being computed everytime while wait() do runs, however, I don’t know how to optimize the code and make it still work.

Script is located in the npc’s character.

local Target
local TargetPosition
local LockOn = false
local Path
local PreviousWaypoint

local HeightsValue = 20
local DetectionDistance = 50

script.Parent.PrimaryPart:SetNetworkOwner(nil)


local function CheckForTarget()
	for i, v in pairs(workspace:GetDescendants()) do
		if script.Parent.Activated.Value == true and v:IsA("Humanoid") and v.Parent and v.Parent:IsA("Model") and v.Parent ~= script.Parent then
			if game.Players:GetPlayerFromCharacter(v.Parent) then
				if v.Parent:FindFirstChild("CanDie") and v.Parent:FindFirstChild("CanDie").Value == true then
					if Target == nil and (v.Parent:FindFirstChild("HumanoidRootPart").Position - script.Parent.HumanoidRootPart.Position).Magnitude <= DetectionDistance or Target ~= nil and (Target.Parent:FindFirstChild("HumanoidRootPart").Position - script.Parent.HumanoidRootPart.Position).Magnitude > (v.Parent:FindFirstChild("HumanoidRootPart").Position - script.Parent.HumanoidRootPart.Position).Magnitude then
						LockOn = true
						TargetPosition = v.Parent:FindFirstChild("HumanoidRootPart").Position
						return v
					end
				end
			end
		end
	end	
end	
local function GetPath(destination)
	Path = game:GetService("PathfindingService"):CreatePath({WaypointSpacing = math.huge})
	Path:ComputeAsync(script.Parent.HumanoidRootPart.Position, destination)
end
while wait() do
	if Target and Target.Parent:FindFirstChild("CanDie") and Target.Parent:FindFirstChild("CanDie").Value == false then
		LockOn = false
	end
	if LockOn == false then
		Target = CheckForTarget()
	end
	if script.Parent.Activated.Value == true and Target ~= nil then
		local LineOfSightRaycastParams = RaycastParams.new()
		LineOfSightRaycastParams.FilterType = Enum.RaycastFilterType.Exclude
		LineOfSightRaycastParams.FilterDescendantsInstances = {script.Parent}
		local LineOfSightRaycast = workspace:Raycast(script.Parent.HumanoidRootPart.Position, (Target.Parent:FindFirstChild("HumanoidRootPart").Position - script.Parent.HumanoidRootPart.Position).Unit * DetectionDistance, LineOfSightRaycastParams)
		GetPath(Target.Parent:FindFirstChild("HumanoidRootPart").Position)
		for i, v in pairs(Path:GetWaypoints()) do
			local GreatHeight = false
			if PreviousWaypoint ~= nil then
				if PreviousWaypoint.Position.Y - v.Position.Y >= HeightsValue then
					GreatHeight = true
				end
			end
			PreviousWaypoint = v
			if LineOfSightRaycast and LineOfSightRaycast.Instance.Parent ~= Target.Parent  or LineOfSightRaycast == nil then
				LockOn = false
				if not GreatHeight then
					script.Parent.Humanoid:MoveTo(v.Position)
					script.Parent.Humanoid.MoveToFinished:Wait(2)
				else
					break
				end
			elseif LineOfSightRaycast and LineOfSightRaycast.Instance.Parent == Target.Parent then
				local HeightRaycastOrigin = script.Parent.HumanoidRootPart.CFrame * CFrame.new(0,0,-2.5)
				local HeightRaycast = workspace:Raycast(HeightRaycastOrigin.Position, Vector3.new(0, -100, 0), LineOfSightRaycastParams)
				if HeightRaycast and HeightRaycastOrigin.Position.Y - HeightRaycast.Position.Y < HeightsValue then
					script.Parent.Humanoid:MoveTo(Target.Parent:FindFirstChild("HumanoidRootPart").Position)
					task.wait()
				else	if HeightRaycast and HeightRaycastOrigin.Position.Y - HeightRaycast.Position.Y >= HeightsValue then
						break
					end
				end	
			end
		end
	end
end

This is a shortened template of my code. How can I make it more optimized while still doing the same thing it is doing aka following the player and avoiding falling from heighs?

1 Like

figured out that the pathfinding isn’t the issue(never turned the activated boolvalue to true in any of my tests), it’s the checks in the while wait() do loop instead. Is there any way to replace the while wait() do loop for something more lag free?

Removing this fixes the lag, gonna test some more on how can I optimize this part.

Use the heartbeat event of the RunService

1 Like

Thank you for the feedback, but I already solved the issue lol.

Also, I should warn you that anything of RunService mixed with PathfindingService is not good due to it creating stutters in the npc’s movement because stuff like Heartbeat and RenderStepped is too fast for the PathfindingService.

for anyone reading this in the future, do not use GetDescendants on server scripts that will be copied multiple times (for example, starter character server scripts), as GetDescendants is VERY expensive.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.