Heya there.
I’ve created a pathfinding module that handles the pathfinding of the majority of the enemies in my game. How it works is simple, if an enemy detects a player near them, target them. Otherwise, target the objective (The thing players are protecting).
The issue is that the enemy’s pathfinding seems to progressively worsens when more enemies spawn as seen in the video below. You can see that the first enemy acts fine, but as more enemies spawn, the first enemy starts to twitch out to the point where they can’t even move.
Here’s the pathfinding module.
--[[SERVICES]]--
local PathfindingService = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
--[[MODULE]]--
local PathfindingModule = {}
function PathfindingModule.Pathfind(NPC, AggroRange)
--//Preperation
local Objective = game.Workspace:FindFirstChild("Crystal")
--Enemy
local RootPart = NPC.PrimaryPart
local Humanoid = NPC.Humanoid
local CharacterSize = NPC:GetExtentsSize()
--RootPart:SetNetworkOwner(nil)
--//Pathfinding Agents
local PathfindingAgents = {
AgentRadius = (CharacterSize.X + CharacterSize.Z)/4,
AgentHeight = CharacterSize.Y,
AgentCanJump = true
}
--[[PATHFINDING]]--
local function FollowPath(Destination)
local NewPath = PathfindingService:CreatePath(PathfindingAgents)
NewPath:ComputeAsync(RootPart.Position, Destination)
if NewPath.Status == Enum.PathStatus.Success then
local Waypoints = NewPath:GetWaypoints()
for _, Waypoint in ipairs(Waypoints) do
if Waypoint.Action == Enum.PathWaypointAction.Jump then
Humanoid.Jump = true
end
--Just in case
NewPath.Blocked:Connect(function(blockedWaypointIdx)
print("The enemy's path is blocked. Recalculating.")
if Objective and Objective.PrimaryPart then
FollowPath(Objective.PrimaryPart.Position)
end
end)
Humanoid:MoveTo(Waypoint.Position)
local Timer = Humanoid.MoveToFinished:Wait(1)
if not Timer then
print("Path timed out. Recalculating.")
if Objective and Objective.PrimaryPart then
FollowPath(Objective.PrimaryPart.Position)
end
end
end
else
print("Path failed. Recalculating. Sorry.")
end
end
local function FindNearestTarget()
local NearestTarget = nil
local PlayerList = Players:GetPlayers()
for _, Player in pairs(PlayerList) do
local Character = Player.Character or Player.CharacterAdded:Wait()
if Character and Character.PrimaryPart then
local Distance = (Character.PrimaryPart.Position - RootPart.Position).Magnitude
if Distance <= AggroRange then
NearestTarget = Character
else
NearestTarget = Objective
end
end
end
return NearestTarget
end
RunService.Heartbeat:Connect(function()
local Target = FindNearestTarget()
if Target and Target.PrimaryPart then
--//Checking distance to be safe.
local Distance = (Target.PrimaryPart.Position - RootPart.Position).Magnitude
if Distance <= AggroRange then
Objective = Target
elseif not Target and Distance >= AggroRange then
Objective = game.Workspace:FindFirstChild("Crystal")
end
else
print("Character's RootPart cannot be found.")
end
if Objective and Objective.PrimaryPart then
FollowPath(Objective.PrimaryPart.Position)
end
end)
end
return PathfindingModule