I've seen many players reporting this problem but i can never seem to update my script to fix this problem. When NPCs are wandering, they always seem to stop and start moving, along with a short pause of animation.
some people say things about humanoid.MoveToFinished:Wait() but i'm not sure if it has anything to do with the script i'm using.
Here is the script I am using, be warned it's long.
local players = Info.Players:GetPlayers()
local closestCharacter, closestCharacterDistance
for i=1, #players do
local player = players[i]
if player.Neutral or player.TeamColor ~= Settings.FriendlyTeam.Value then
local character = player.Character
if character ~= nil and character:FindFirstChild('Humanoid') ~= nil and character.Humanoid:IsA('Humanoid') then
local distance = player:DistanceFromCharacter(Monster:GetCFrame().p)
if distance < Monster:GetMaximumDetectionDistance() then
if closestCharacter == nil then
closestCharacter, closestCharacterDistance = character, distance
else
if closestCharacterDistance > distance then
closestCharacter, closestCharacterDistance = character, distance
end
end
end
end
end
end
if closestCharacter ~= nil then
Mind.CurrentTargetHumanoid.Value = closestCharacter.Humanoid
end
end
function Monster:TryRecomputePath()
if Data.AutoRecompute or tick() - Data.LastRecomputePath > 1/Info.RecomputePathFrequency then
Monster:RecomputePath()
end
end
function Monster:GetTargetCFrame()
local targetHumanoid = Mind.CurrentTargetHumanoid.Value
if Monster:TargetIsValid() then
return targetHumanoid.Torso.CFrame
else
return CFrame.new()
end
end
function Monster:IsAlive()
return Self.Humanoid.Health > 0 and Self.Humanoid.Torso ~= nil
end
function Monster:TargetIsValid()
local targetHumanoid = Mind.CurrentTargetHumanoid.Value
if targetHumanoid ~= nil and targetHumanoid:IsA 'Humanoid' and targetHumanoid.Torso ~= nil and targetHumanoid.Torso:IsA 'BasePart' then
return true
else
return false
end
end
function Monster:HasClearLineOfSight()
-- Going to cast a ray to see if I can just see my target
local myPos, targetPos = Monster:GetCFrame().p, Monster:GetTargetCFrame().p
local hit, pos = Workspace:FindPartOnRayWithIgnoreList(
Ray.new(
myPos,
targetPos - myPos
),
{
Self,
Mind.CurrentTargetHumanoid.Value.Parent
}
)
if hit == nil then
return true
else
return false
end
end
function Monster:RecomputePath()
if not Data.Recomputing then
if Monster:IsAlive() and Monster:TargetIsValid() then
if Monster:HasClearLineOfSight() then
Data.AutoRecompute = true
Data.PathCoords = {
Monster:GetCFrame().p,
Monster:GetTargetCFrame().p
}
Data.LastRecomputePath = tick()
Data.CurrentNode = nil
Data.CurrentNodeIndex = 2 -- Starts chasing the target without evaluating its current position
else
-- Do pathfinding since you can't walk straight
Data.Recomputing = true -- Basically a debounce.
Data.AutoRecompute = false
local path = Info.PathfindingService:ComputeSmoothPathAsync(
Monster:GetCFrame().p,
Monster:GetTargetCFrame().p,
500
)
Data.PathCoords = path:GetPointCoordinates()
Data.Recomputing = false
Data.LastRecomputePath = tick()
Data.CurrentNode = nil
Data.CurrentNodeIndex = 1
end
end
end
end
function Monster:Update()
Monster:ReevaluateTarget()
Monster:SearchForTarget()
Monster:TryRecomputePath()
Monster:TravelPath()
end
function Monster:TravelPath()
local closest, closestDistance, closestIndex
local myPosition = Monster:GetCFrame().p
local skipCurrentNode = Data.CurrentNode ~= nil and (Data.CurrentNode - myPosition).magnitude < 3
for i=Data.CurrentNodeIndex, #Data.PathCoords do
local coord = Data.PathCoords[i]
if not (skipCurrentNode and coord == Data.CurrentNode) then
local distance = (coord - myPosition).magnitude
if closest == nil then
closest, closestDistance, closestIndex = coord, distance, i
else
if distance < closestDistance then
closest, closestDistance, closestIndex = coord, distance, i
else
break
end
end
end
end
--
if closest ~= nil then
Data.CurrentNode = closest
Data.CurrentNodeIndex = closestIndex
local humanoid = Self:FindFirstChild 'Humanoid'
if humanoid ~= nil and humanoid:IsA'Humanoid' then
humanoid:MoveTo(closest)
end
if Monster:IsAlive() and Monster:TargetIsValid() then
Monster:TryJumpCheck()
Monster:TryAttack()
end
if closestIndex == #Data.PathCoords then
-- Reached the end of the path, force a new check
Data.AutoRecompute = true
end
end
end
Hope there is something that can be done about this. Also, sorry for the long script again.

2 comments
Same i figured out it takes some time for it to recalculate a path to a player for my npc it stops more the closer it gets to the player ...stops as in kinda bumpy stopping
Exactly, but my NPCs stop when trying to walk around solid parts, if the player were to be in a straight line from the NPC without any obstacles, then it will not lag