I’m rewriting a OOP NPC System. The issue I’m having is that the NPC prematurely stops before moving again. I know this is because of how the Pathfind function works as I’m skipping the first waypoint to prevent the NPC from only moving to original position of its enemies. The issue is that I don’t know a way to not only skip the first waypoint but also constantly move.
--[[SERVICES]]--
local Players = game:GetService("Players")
local PathfindingService = game:GetService("PathfindingService")
--[[NPC MODEL FOLDERS]]--
local NPCFolder = game:GetService("ServerScriptService").NPCS
local NoobsFolder = NPCFolder.Noobs
--[[MODULE]]--
local BaseNPCModule = {}
BaseNPCModule.__index = BaseNPCModule
function BaseNPCModule:CreateNPC(UnitName, UnitTeam, Special)
--//Checking to see if the unit exists.
for _, FindUnit in pairs(NoobsFolder:GetChildren()) do
if FindUnit:IsA("Model") and FindUnit.Name == UnitName then
--//Creating the unit.
self.Unit = FindUnit:Clone()
self.Humanoid = self.Unit:FindFirstChildWhichIsA("Humanoid")
self.Unit.Parent = game.Workspace
self.UnitTeam = game:GetService("CollectionService"):AddTag(self.Unit, UnitTeam)
self.Is_Special = Special
--//Giving it functionality
task.spawn(function()
task.wait(1)
while task.wait() do
local Target = BaseNPCModule:FindNearestTargets()
if Target then
BaseNPCModule:Pathfind(Target)
end
end
end)
end
end
end
function BaseNPCModule:FindNearestTargets()
local Target = nil
for _, PossibleTargets in ipairs(workspace:GetChildren()) do
if PossibleTargets:IsA("Model") and PossibleTargets:FindFirstChildWhichIsA("Humanoid") then
local Humanoid = PossibleTargets:FindFirstChildWhichIsA("Humanoid")
if Humanoid.Health <= 1 then
--//They're dead.
return
end
--//If they aren't dead, check the distance.
local Distance = (PossibleTargets.PrimaryPart.Position - self.Unit.PrimaryPart.Position).Magnitude
if Distance <= math.huge then
if PossibleTargets:HasTag("Zombies") then
Target = PossibleTargets
end
end
end
end
return Target
end
function BaseNPCModule:Pathfind(Target)
local NewPath = PathfindingService:CreatePath()
NewPath:ComputeAsync(self.Unit.PrimaryPart.Position, Target.PrimaryPart.Position)
if NewPath.Status == Enum.PathStatus.Success then
local Waypoints = NewPath:GetWaypoints()
for i, Waypoint in ipairs(Waypoints) do
if i <= 2 then continue end
if Waypoints[4] then
self.Humanoid:MoveTo(Waypoints[4].Position)
local TimeOut = self.Humanoid.MoveToFinished:Wait()
if not TimeOut then
warn("NPC got stuck... Recalculating!")
BaseNPCModule:Pathfind(Target)
end
end
end
end
end
return BaseNPCModule
After reviewing your code, it was just a missing task.spawn when calling the Pathfind function making it yield until the NPC finished moving
Here’s your fixed code
--[[SERVICES]]--
local Players = game:GetService("Players")
local PathfindingService = game:GetService("PathfindingService")
--[[NPC MODEL FOLDERS]]--
local NPCFolder = game:GetService("ServerScriptService").NPCS
local NoobsFolder = NPCFolder.Noobs
--[[MODULE]]--
local BaseNPCModule = {}
BaseNPCModule.__index = BaseNPCModule
function BaseNPCModule:CreateNPC(UnitName, UnitTeam, Special)
--//Checking to see if the unit exists.
for _, FindUnit in pairs(NoobsFolder:GetChildren()) do
if FindUnit:IsA("Model") and FindUnit.Name == UnitName then
--//Creating the unit.
self.Unit = FindUnit:Clone()
self.Humanoid = self.Unit:FindFirstChildWhichIsA("Humanoid")
self.Unit.Parent = game.Workspace
self.UnitTeam = game:GetService("CollectionService"):AddTag(self.Unit, UnitTeam)
self.Is_Special = Special
--//Giving it functionality
task.spawn(function()
while task.wait(0.05) do
task.spawn(function()
local Target = BaseNPCModule:FindNearestTargets()
if Target then
BaseNPCModule:Pathfind(Target)
end
end)
end
end)
end
end
end
function BaseNPCModule:FindNearestTargets()
local Target = nil
for _, PossibleTargets in ipairs(workspace:GetChildren()) do
if PossibleTargets:IsA("Model") and PossibleTargets:FindFirstChildWhichIsA("Humanoid") then
local Humanoid = PossibleTargets:FindFirstChildWhichIsA("Humanoid")
if Humanoid.Health <= 1 then
--//They're dead.
return
end
--//If they aren't dead, check the distance.
local Distance = (PossibleTargets.PrimaryPart.Position - self.Unit.PrimaryPart.Position).Magnitude
if Distance <= math.huge then
if PossibleTargets:HasTag("Zombies") then
Target = PossibleTargets
end
end
end
end
return Target
end
function BaseNPCModule:Pathfind(Target)
local NewPath = PathfindingService:CreatePath({
AgentRadius = 3,
AgentHeight = 5,
AgentCanJump = true,
})
NewPath:ComputeAsync(self.Unit.PrimaryPart.Position, Target.PrimaryPart.Position)
if NewPath.Status == Enum.PathStatus.Success then
local Waypoints = NewPath:GetWaypoints()
for i, Waypoint in ipairs(Waypoints) do
if i <= 2 then continue end
if Waypoints[4] then
self.Humanoid:MoveTo(Waypoints[4].Position)
local TimeOut = self.Humanoid.MoveToFinished:Wait()
if not TimeOut then
warn("NPC got stuck... Recalculating!")
BaseNPCModule:Pathfind(Target)
end
end
end
end
end
return BaseNPCModule