I have a incomplete zombie pathfinding script and when I leave it running for a certain amount of time , my frames gradually become worse. Here is the script :
local isMoving = false
local humanoid = script.Parent.Humanoid
local model = script.Parent
local PFS = game:GetService(“PathfindingService”)
local agroDistance = 150
local blackListedParts = {}
while true do
wait()
local entireWorkSpace = game.Workspace:GetChildren()
local possibleTargets = {}
for i,v in pairs(entireWorkSpace) do
if v:FindFirstChild("Humanoid") and v.Parent ~= script.Parent then
possibleTargets[i] = v:FindFirstChild("UpperTorso")
end
end
local closestTarget = game.Workspace.referencePart
for i,v in pairs(possibleTargets) do
if (closestTarget.Position - model.UpperTorso.Position).Magnitude > (v.Position - model.UpperTorso.Position).Magnitude then
if v.Parent ~= model then
closestTarget = v
end
end
end
if closestTarget then
print("is Human")
if (closestTarget.Position - model.HumanoidRootPart.Position).Magnitude <= agroDistance then
local params = RaycastParams.new()
local maginitude = (closestTarget.Position - model.HumanoidRootPart.Position).Magnitude
for i,v in pairs(entireWorkSpace) do
if v:FindFirstChild("Humanoid") then
for a,b in pairs(v:GetChildren()) do
if b:IsA("MeshPart") or b:IsA("Accessory") or b:IsA("Part") then
table.insert(blackListedParts,b)
end
end
end
end
params.FilterDescendantsInstances = blackListedParts
params.FilterType = Enum.RaycastFilterType.Blacklist
local rayCastResults = game.Workspace:Raycast(model.UpperTorso.Position,(closestTarget.Position-model.UpperTorso.Position).Unit*(maginitude-1),params)
if rayCastResults then
humanoid:MoveTo(model.UpperTorso.Position)
local path = PFS:CreatePath()
path:ComputeAsync(model.UpperTorso.Position,closestTarget.Position)
else
humanoid:MoveTo(closestTarget.Position)
table.clear(blackListedParts)
end
else
if isMoving == false then
humanoid:MoveTo(model.UpperTorso.Position + Vector3.new(math.random(-30,30),model.UpperTorso.Position.Y,math.random(-30,30)))
isMoving = true
table.clear(blackListedParts)
end
end
end
I can see one problem. Most scripters advise against using wait(). You may want to use RunService.Heartbeat:wait() instead, or a similar function of RunService.
In addition, you may want to consider changing how the script looks for targets. If it is only looking for players, you can just iterate through everyone in game.Players, checking if their characters exist and accessing them that way (each player has a Character property that points to their corresponding character model in the Workspace). Doing this would drastically reduce the runtime of the for loop.
If the zombie is looking for non-player targets as well, you may want to consider grouping all NPC’s in a single model (or Folder) and looking through all children of both that and Players, unless you need NPC’s to be grouped within other models. I have yet to do this myself, but I have plans to do something similar and figured sharing the idea may help.
You should really put the players that join and/or NPCs in a table so that way the loops don’t have to check every single part that there’s in the workspace.
Also like said above, you might want to use RunService.Heartbeat:Wait() instead of a while loop.
I have made it so that the code runs off heartbeat and I have made a module script that has all the players and NPC character models and I am looping through that instead but now the lag has gotten even worse. My entire studio almost crashed.
Edit : the almost crashing part only happens once a player/NPC is in the zombies agro distance.
It still does not explain the lag , because it is not the part where it loops through the player models but when they player is in range of the zombie , here :
if rayCastResults then
humanoid:MoveTo(model.UpperTorso.Position)
local path = PFS:CreatePath()
path:ComputeAsync(model.UpperTorso.Position,closestTarget.Position)
else
humanoid:MoveTo(closestTarget.Position)
table.clear(blackListedParts)
end
else
if isMoving == false then
humanoid:MoveTo(model.UpperTorso.Position + Vector3.new(math.random(-30,30),model.UpperTorso.Position.Y,math.random(-30,30)))
isMoving = true
table.clear(blackListedParts)
end
end
Can you try removing this part of your code (line 2-3 in the snippet)? You’re not using it at all. You could also clear blackListedParts in this branch too.
Try using the isMoving variable to implement a debounce in that script since it seems like once the player is in range it keeps firing every single frame. Or just a debounce in general.
Although this may cause the zombie to not change directions at all until it reaches the end of the computed path.
sorry i took so long ive been busy all day but task.wait() is just a better wait() and fixes loop lag/fps drops (i always forgot what it means and what its for)
Heartbeat was a bad idea because it was able to fire even before the loop could finish because there were sections of the loop that waited until the NPC/ Player had completed their movement , therefor there were way too many firing at once.