Pathfinding FPS Drop

Hey all,

I’m making a remake of a game called Infectonator on Roblox, and a major part of the game is the mass amounts of NPCS like survivors and zombies chasing said survivors.

It’s been working well until I’ve started getting insanely huge frame drops (5-10 FPS) a little after I set some zombies down, when looking at the microprofiler there has been a very long bar on the NavigationJob and WorkerJob sections.

Here is my code, the MoveTo is usually called on every heartbeat, in which I put a debounce of 2 seconds for a path to be attempted, still to no avail.

The NPC’s models are only rendered on the client and are anchored invisible parts on the server.

Would really appreciate some help on this, as It’s been frustrating me for the past week.

pic

Pathfinding Code


function module:StopPath()
	self.Model:SetAttribute("Moving", false)
	self.pathID += 1
	
	if self.moveTween then
		self.moveTween:Cancel()
	end
	
	self.currRotation.Value = newCFrame(self.Model.Position, self.Model.Position + newVector3(math.cos(math.random(-pi, pi)), 0, math.sin(math.random(-pi, pi))))
end

function module:MoveTo(endpos)
	if not self.Model.Parent or self.Model:GetAttribute("stunned") or self.pathDebounce < 2 then
		return
	end
	
	self.pathDebounce = 0
	
	endpos = newVector3(endpos.X, self.Model.Position.Y, endpos.Z)
	local vec = (endpos - self.Model.Position)
	local result = workspace:Raycast(self.Model.Position, vec.Unit * vec.Magnitude, params)
	
	local path = {}
	
	if not result then
		table.insert(path, "")
		table.insert(path, {Position = endpos})
	else
		self.path:ComputeAsync(self.Model.Position, endpos)
		
		if self.path.Status == Enum.PathStatus.Success then
			local waypoints = self.path:GetWaypoints()
			for i = 1,#waypoints do
				table.insert(path, {Position = waypoints[i].Position + newVector3(0, self.Height/2, 0)})
			end
		else
			self:StopPath()
			return
		end
	end
	
	self.pathID += 1
	local currentID = self.pathID
	
	self.Model:SetAttribute("Moving", true)
	
	local function nextWaypoint(i)
		if not self.Model.Parent or currentID ~= self.pathID or self.Model:GetAttribute("stunned") then
			return
		end
		
		local waypointPos = path[i].Position
		local initial = self.Model.Position

		local timeneeded = (newVector3(waypointPos.X, 0, waypointPos.Z) - newVector3(initial.X, 0, initial.Z)).Magnitude/self.speed

		if not self.attacking then	
			self.currRotation.Value = newCFrame(initial, waypointPos)
		end
		
		if self.moveTween then
			self.moveTween:Destroy()
		end

		local tween = tweenService:Create(self.Model, TweenInfo.new(timeneeded, Enum.EasingStyle.Linear), {Position = waypointPos})
		self.moveTween = tween
		
		tween:Play()
		tween.Completed:Wait()
		
		if i < #path then
			nextWaypoint(i + 1)
		elseif currentID == self.pathID then
			self:StopPath()
		end
	end
	
	wrapCoroutine(nextWaypoint)(2)
	
	return true
end

hello, have you found a solution? I also have the same problem.