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.
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