Recently, I’ve been working on an enemy pathfinding system for a COD style game. I’ve managed to finish the system in a way that’s both optimized and very fast, but when stress testing with dozens of enemies, I noticed that, the longer the game ran for, the slower the pathfinding system would update each enemy. Their paths start refreshing much, much slower, causing them to freeze for a long time before finding a new path. I don’t know exactly why, given no errors or warnings appear, but I have a strong suspicion it’s because of the amount of path requests I make in a short amount of time.
I want to ask: What are some ways I can cut down on path refreshes? I’m already skipping a refresh if enemies are too far away or if the target hasn’t moved a significant distance. I’ve read about caching paths, but I’m not sure how I’d implement that, given enemies need to chase players up close.
--Code snippet relevant to pathfinding requests. The Pathfinding itself is a simple Pathfinding:CreatePath() and Pathfinding:ComputeAsync() system.
local UpdatesPerSecond = 4
local Interval = 1 / UpdatesPerSecond
local accumulator = 0
local function PathfindingRefreshAllowed(Origin : Vector3, LastTarget : Vector3) : boolean
local closestPlayer = nil
local closestDistance = nil
for i, Plrs in Players:GetPlayers() do
if Plrs.Team == Teams.Dead or not Plrs.Character then continue end
local primaryPart = Plrs.Character.PrimaryPart
local PlayerPos = Vector3.new(primaryPart.Position.X, Origin.Y, primaryPart.Position.Z)
local dist = (PlayerPos - Origin).Magnitude
if not closestPlayer or dist < closestDistance then
closestPlayer = PlayerPos
closestDistance = dist
end
end
if not closestDistance then return end
if closestDistance > 60 then
--print("Closest player is too far away. Path cannot refresh.")
return false
end
if LastTarget and (LastTarget - closestPlayer).Magnitude <= 2 then
-- print("Target is too to the last check. Path cannot refresh.")
return false
end
return true
end
-- MAIN ENEMY PATHFINDING
RunService.Heartbeat:Connect(function(DT)
accumulator += DT
for ID, info in EnemyStorage.GetEnemies() do
if #info.Waypoints == 0 then
EnemyPathFinder(info.Position, ID)
continue
end
local currentPosition = info.Position
local goal = info.Waypoints[1]
local speed = info.Speed
local direction = (goal - currentPosition).Unit
local newPosition = currentPosition + direction * speed * DT
EnemyStorage.Move(ID, newPosition, info.DebugPart)
end
while accumulator >= Interval do
accumulator -= Interval
module.UpdateAllPaths()
module.ClientSend()
end
end)
function module.UpdateAllPaths()
for ID, info in EnemyStorage.GetEnemies() do
if not PathfindingRefreshAllowed(info.Position, info["LastTarget"]) then continue end
EnemyPathFinder(info.Position, ID)
end
end
Thanks in advance!