I created this pathfinding module for NPC’s but it is not well optimized. My device isn’t that good but I still managed to get 20 FPS with game quality set to max and a cluster of 70 NPC’s chasing my character (with almost empty baseplate). I tried to optimize it as best I could, but I just don’t seem to get anywhere. Here is the modulescript:
local pathfinding = {}
function pathfinding.Handle(NPC)
local PathfindingService = game:GetService("PathfindingService")
NPC.PrimaryPart:SetNetworkOwner(nil)
local path=PathfindingService:CreatePath()
local range = NPC.Range.Value --range = 30
local currenttarget
--disabling useless humanoidstates
NPC.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Climbing, false)
NPC.Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
NPC.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Ragdoll, false)
NPC.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Seated, false)
NPC.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Swimming, false)
NPC.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Dead, false)
NPC.Humanoid:SetStateEnabled(Enum.HumanoidStateType.StrafingNoPhysics, false)
NPC.Humanoid:SetStateEnabled(Enum.HumanoidStateType.FallingDown, false)
NPC.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Flying, false)
--anchoring or unanchoring NPC's HumanoidRootPart based on speed
NPC.Humanoid.Running:Connect(function(speed)
if speed == 0 then
if not NPC.PrimaryPart.Anchored then --NPC.PrimaryPart is HumanoidRootPart
NPC.PrimaryPart.Anchored = true
else
if NPC.PrimaryPart.Anchored then NPC.PrimaryPart.Anchored = false end
end
end
end)
while wait(0.4) do
if not NPC.PrimaryPart then break end --if no NPC, then break
for i, plr in ipairs(game:GetService("Players"):GetPlayers()) do
if plr.Character then
if plr:DistanceFromCharacter(NPC.PrimaryPart.Position) <= range then --not using .magnitude
if not currenttarget then
currenttarget = plr
else
if plr~=currenttarget and (plr:DistanceFromCharacter(NPC.PrimaryPart.Position) < currenttarget:DistanceFromCharacter(NPC.PrimaryPart.Position)) then
currenttarget = plr
end
end
end
end
end
if currenttarget then
if currenttarget.Character.PrimaryPart then
NPC.PrimaryPart.Anchored = false
local ray = Ray.new(NPC.PrimaryPart.Position, currenttarget.Character.PrimaryPart.Position - NPC.PrimaryPart.Position) --a ray from npc to player
local part = workspace:FindPartOnRayWithIgnoreList(ray, {NPC, currenttarget.Character})
if part then --pathfind
path:ComputeAsync(NPC.PrimaryPart.Position,currenttarget.Character.PrimaryPart.Position)
local waypoints = {}
if path.Status == Enum.PathStatus.Success then
waypoints = path:GetWaypoints()
for i,point in pairs(waypoints) do
if i < 6 then --6 is the maximum number of waypoints NPC can MoveTo because the while loop will make new waypoints for NPC to go to. this should increase if NPC's Walkspeed is increased
if point.Action == Enum.PathWaypointAction.Jump then
NPC.Humanoid.Jump = true
end
NPC.Humanoid:MoveTo(point.Position)
--repeat wait() until (NPC.PrimaryPart.Position-point.Position).magnitude < 0.2 --if i enable this (or MoveToFinished:Wait()), the NPC anchors forever (or it just breaks)
end
end
else
NPC.Humanoid:MoveTo(NPC.HumanoidRootPart.Position)
end
else
NPC.Humanoid:MoveTo(currenttarget.Character.PrimaryPart.Position) --if the player and NPC have nothing in between them blocking their path, then NPC doesnt need to pathfind. or does it? at least increases performance
end
end
end
end
end
return pathfinding
Please dont just say “you are computing a new path way to fast” or “you should wait longer between points” or something because I tried it, but the NPC is not responsive and just seems to lag behind or pathfinding breaks.