We have been working on a defense game that includes waves of enemies with pathfinding. During playtest we noticed that the server memory usage immediately went up to 3,500 MB minimum and 4,600 MB maximum. Upon checking we found out that the AI scripts were actually the main cause of the excessive memory consumption.
The solution we tried was to create the path instance only once, expecting that it would be enough to reduce memory consumption.
Is it true that the pathfinding service can really cause memory leaks? If so, do you have any suggestions to avoid or minimize such leaks caused by the pathfinding service?
Any help is appreciated.
local wp do
local success = pcall(function() return Path:ComputeAsync(Torso.Position, Destination) end)
if success and Path.Status == Enum.PathStatus.Success and Path:GetWaypoints() > 2 then
wp = Path:GetWaypoints()[3]
end
CurrentWaypoint = wp
end
With this code, All the memory usage is in untracked memory which never gets garbage collected.
I am the friend of OP who works with me personally. We’ve tried the following solutions.
Reducing the interval of which the path is computed.
Destroying the path immediately after it is computed.
None of these solutions actually solved it and only served as bandaids.
The real code looks like this.
local m, e, k, z = script.Parent, script.Parent.Name, script.Parent:FindFirstChild("Head"), script.Parent:FindFirstChildOfClass("Humanoid") do
while k.Parent == script.Parent and z:GetState() ~= Enum.HumanoidStateType.Dead do
local wp do
if n and (n.Position- k.Position).magnitude > 20 then
if temp < 5 then
if did then
if temp2 <= 0 then
--print("back to do")
did = false
end
else
local st, pth = pcall(function() return pathfindingService:FindPathAsync(k.Position,n.Position) end)
if st and pth and pth.Status == Enum.PathStatus.Success then
local wps = pth:GetWaypoints()
if table.getn(wps) > 0 then
wp = wps[math.min(table.getn(wps), math.floor(z.WalkSpeed/5))] --set this to 5 if your npc is fast, to avoid jittering
--workspace.Effect.Position = wp.Position
end
end
end
else
--print("blocked")
did = true
temp2 = 5
end
end
end
--if wp then
-- print("by wp")
--end
temp = lp == floorVec3(wp and wp.Position or l) and temp + 1 or 0
if active.Value then
ls = true
z:MoveTo(wp and wp.Position or l, n)
elseif not wp and ls then
ls = false
z:MoveTo(script.Parent.HumanoidRootPart.Position)
end
if wp and wp.Action == Enum.PathWaypointAction.Jump then
z.Jump = true
end
--z:MoveTo(l, a)
d = p
lp = floorVec3(wp and wp.Position or l)
task.wait(wp and f/20 or f/5)
end
end
You can ignore some of the variables here since they are not that important, but I think the rest is actually easy to read if you have a healthy attention span but i’ll explain it to you.
This is a while loop that creates a path instance every .05 seconds assuming the NPC’s walkspeed is 16, the f Variable is supposed to be 17 divided by the NPC’s Walkspeed if the target is more than 20 studs away from the NPC. else it will follow the target every .2 seconds.