Retry on trying to get help on AI causing memory leaks and lag

I have been dealing with this problem for around 6 months now which is that the AI of enemies in a game i’m trying to make is causing memory leakages and lag. These memory leakages would appear as spikes in memory instead of gradual increases in memory which would happen for no apparent reason. I think i need help with solving this with someone in studio because this problem is so hard for me to fix let alone completely find.

I’ve tried:reducing the interval of which a path is computed.
I’ve tried creating the path instance only once, then destroying it when it’s no longer needed, such as when the npc dies or is destroyed.

And the lag also occurs even when less than 20 enemies are present. in fact the game had lag spikes like this when there was just 1 - 11 enemies on the map. i don’t know why this is happening but it’s not fun to deal with.
The npcs pathfinding would also have trouble using their pathfinding as they would often be ramming towards a wall, which i think is a result of the lag.

To note, the map the enemies are placed on is super large, around 2 baseplates in length.


image
image

Cope Snippets:

-- Debounces
local Blocked = false
local Pathing = false

-- Essentials
local TargetToMoveTo
local MoveTo
local Waypoint
local print = DebugMode and print or function() end
local CurrentIndex
local PathParams = {AgentHeight = Character:GetModelSize().Y, AgentRadius = Character:GetModelSize().X, AgentCanJump = CanJump, AgentCanClimb = CanClimb, WaypointSpacing = Spacing, Costs = CostConfigs}
local Path:Path = PathfindingService:CreatePath{table.unpack(PathParams)}
local BlockConn

task.spawn(function() -- Get Target
	while task.wait(.2) and Humanoid:GetState() ~= Enum.HumanoidStateType.Dead do
		local Check = GetNearestTarget(Docile and Range.Value or math.huge, Root.Position, false)
		TargetToMoveTo = Check ~= nil and Check or TargetToMoveTo
	end
end)

local function Main(Position, Part:BasePart)
	if Position then
		local Mag = (Root.Position - Position).Magnitude
		if Mag > Range.Value or Part and not CheckSight(Part) then
			local Success = pcall(function() Path:ComputeAsync(Root.Position, Position)  end) -- the current assumption is that waypoints are causing high memory usage
			local CurrentIndex = 0

			if Success and  Path and Path.Status == Enum.PathStatus.Success then
				--print("Success")
				Pathing = true
				Blocked = false
				BlockConn = Path.Blocked:Connect(function(BlockedIndex) -- Make this a one time connection from what i figured
					if BlockedIndex >= CurrentIndex then
						print("Lol blocked")
						Blocked = true
					end 
				end)
				local Points:{PathWaypoint} = Path:GetWaypoints()
				if DebugMode then
					DebugPath(Points)
				end
				task.spawn(function()
					for i, v in Points do
						if not Active.Value or Humanoid:GetState() == Enum.HumanoidStateType.Dead or not Pathing then
							break
						end
						print("Waypointed")
						Waypoint = v
						CurrentIndex = i
						task.wait((16/Humanoid.WalkSpeed)/4)
					end
				end)
			else
				print("Path creation unsuccessful")
			end
		end
	end
end

task.spawn(function() -- Make Path
	repeat
		if TargetToMoveTo and not CheckSight(TargetToMoveTo) then
			--if Main() then
			Main(TargetToMoveTo.Position, TargetToMoveTo)
			local Waits = 0
			local Sight
			repeat
				Sight = CheckSight(TargetToMoveTo)
				Waits += task.wait(.2)
				print("waiting")
			until Waits >= 2 or Blocked or Sight
			if BlockConn then
				BlockConn:Disconnect()
			end
			print("resetting")
			--if Path then
			--	Path:Destroy() -- Destroy it every 2 seconds and create a new one
			--	task.wait()
			--	Path = nil	
			Waypoint = nil
			--end
			--end
			Pathing = false
		else
			task.wait()
		end

	until Humanoid:GetState() == Enum.HumanoidStateType.Dead
end)

local function Clean()
	Waypoint = nil
	for i, v in VisibleWaypoints do
		v:Destroy()
	end
	table.clear(VisibleWaypoints)
	if Path then 
		Path:Destroy() 
	end
	Path = nil
end


Humanoid.Died:Connect(Clean)
Character.Destroying:Connect(Clean)

try this it should be more efficient

local PathfindingService = game:GetService("PathfindingService")
local RunService = game:GetService("RunService")

local TargetToMoveTo = nil
local Path = nil
local Moving = false
local Blocked = false

local function ComputePath()
    if TargetToMoveTo then
        local path = PathfindingService:CreatePath({
            AgentHeight = Character:GetModelSize().Y,
            AgentRadius = Character:GetModelSize().X,
            AgentCanJump = CanJump,
            AgentCanClimb = CanClimb,
            WaypointSpacing = Spacing,
            Costs = CostConfigs
        })

        path:ComputeAsync(Root.Position, TargetToMoveTo.Position)
        return path
    end
    return nil
end

local function MoveToWaypoint()
    local waypoints = Path:GetWaypoints()
    local waypointCount = #waypoints
    local i = 1
    while Moving and i <= waypointCount do
        Waypoint = waypoints[i]
        task.wait((16 / Humanoid.WalkSpeed) / 4)
        i = i + 1
    end
end

local function Main()
    while true do
        if not Moving and TargetToMoveTo then
            Moving = true
            Path = ComputePath()
            if Path and Path.Status == Enum.PathStatus.Success then
                Blocked = false
                local success, message = pcall(MoveToWaypoint)
                if not success then
                    print("Error while moving: " .. message)
                end
            else
                print("Path creation unsuccessful")
                Blocked = true
            end
            Moving = false
        end
        task.wait()
    end
end

local function GetTarget()
    while true do
        task.wait(.2)
        if Humanoid:GetState() == Enum.HumanoidStateType.Dead then return end
        local check = GetNearestTarget(Docile and Range.Value or math.huge, Root.Position, false)
        TargetToMoveTo = check or TargetToMoveTo
    end
end

local function Clean()
    TargetToMoveTo = nil
    Moving = false
    Blocked = false
    Waypoint = nil
    if Path then
        Path:Cancel()
        Path = nil
    end
end

RunService.Heartbeat:Connect(Main)
task.spawn(GetTarget)
Humanoid.Died:Connect(Clean)
Character.Destroying:Connect(Clean)

Cancel is not a valid member of path instance
i’ve had path instances be created multiple times like this and memory leakages would occur

i don’t understand how this will be any more efficient.