I'm making an office with NPC employees that walk around. They go from stations, meetings, to the break room, and etc.

When the npc's are first spawned they walk perfectly fine to their next station, but after a set amount of time when they go to their next, they walk super slow and jolty. Very similarly to the NPC in this video: https://i.gyazo.com/4571575e0383753710c1b35ec7bd2df7.mp4

here's the code (all of my npc scripts are regular scripts & not local btw)

local PathfindingService = game:GetService("PathfindingService")
local char = script.Parent.Parent
local RepStorage = game:GetService("ReplicatedStorage")
local hrp = char.HumanoidRootPart

if hrp:CanSetNetworkOwnership() then
	hrp:SetNetworkOwner(nil) -- setting the owner to the server
end

local function GoToNexStation ()
	wait()
	local destination1 = game.Workspace[char.PathFinding.NexStation.Value]
	local destination = Vector3.new((destination1.Position.X), (hrp.Position.Y), (destination1.Position.Z))
	local waypoints = {}
	local currentWaypointIndex = 0
	local agentParams = {
		["AgentHeight"] = 5,
		["AgentRadius"] = 2,
		["AgentCanJump"] = true,
		["WayPointSpacing"] = 4
	}
	
	local path = PathfindingService:CreatePath(agentParams)
	
	local function followPath()
		path:ComputeAsync(hrp.Position, destination)
		waypoints = {}
		
		if path.Status == Enum.PathStatus.Success then
			waypoints = path:GetWaypoints()	
			currentWaypointIndex = 1
			for i, waypoint in pairs(waypoints) do
				if char.Name == "Gale" then
					print(currentWaypointIndex, " / ", #waypoints)
				end
				if waypoints[currentWaypointIndex] ~= nil then
					if currentWaypointIndex <= #waypoints then
						if waypoints[currentWaypointIndex].Action == Enum.PathWaypointAction.Jump then
							char.Humanoid.Jump = true
						end
						local evt = Instance.new("BindableEvent")
						delay(2, function() 
							if evt then 
								evt:Fire("Timeout") 
							end 
						end)
						char.Humanoid.MoveToFinished:Connect(function() if evt then evt:Fire("Finished") end end)
						
						if currentWaypointIndex <= #waypoints then
							char.Humanoid:MoveTo(waypoints[currentWaypointIndex].Position)
						end
						
						local result = evt.Event:Wait()
						evt:Destroy()
						evt = nil
						if result == "Timeout" then
							char.Humanoid.Jump = true
							currentWaypointIndex = #waypoints + 1 -- cancel out
							GoToNexStation ()
							return {status = 0}
						end
						
						
				
						if currentWaypointIndex == #waypoints then
							char.HumanoidRootPart.CFrame = CFrame.new(destination1.Position) * CFrame.Angles(math.rad(destination1.Orientation.X), math.rad(destination1.Orientation.Y), math.rad(destination1.Orientation.Z))
							char.PathFinding.CurStation.Value = char.PathFinding.NexStation.Value
						end
						currentWaypointIndex = currentWaypointIndex + 1
					end
				end
			end
			return {status = 1}
		else
			if char.PathFinding.CurStation.Value ~= char.PathFinding.NexStation.Value then
				print("failure")
				currentWaypointIndex = #waypoints + 1 -- cancel out
				GoToNexStation ()
			end
		end
	end
	
local function onPathBlocked(blockedWaypointIndex)
		print("Blocked")
			currentWaypointIndex = #waypoints + 1 -- cancel out
		GoToNexStation ()
		return
	end

From what I've read people have all said its either from spamming :MoveTo in a loop or from Network Ownership

I do have it print each time the player walks to a station or starts a new path, so I'm 99% positive it has nothing to do with spamming :MoveTo. I also implemented a bunch of returns and ways to stop the script from spamming it.

I've tried setting the network owner in the script I use to spawn them (separate script from above) where I used this code:

local npc = game.Workspace:FindFirstChild("Noob"):Clone()
local function setNetworkOwnerOfModel(model, networkOwner)
			for _, descendant in pairs(model:GetDescendants()) do
				-- Go through each part of the model
				if descendant:IsA("BasePart") then
					-- Try to set the network owner
					local success, errorReason = descendant:CanSetNetworkOwnership()
					if success then
						descendant:SetNetworkOwner(networkOwner)
					else
						-- Sometimes this can fail, so throw an error to prevent
						-- ... mixed networkownership in the 'model'
						error(errorReason)
					end
				end
			end
		end
		setNetworkOwnerOfModel(npc, nil)

The odd thing is that it sometimes happens & sometimes doesn't. Although it usually does. I believe it could have something to do with the "blocked" function, or the else statement I put for if the path:ComputeAsync doesn't == success. But I could be wrong and it could be something else. I'm genuinely so confused.

There's a lot of different articles on "NPC pathfinding staggering" but I just can't seem to find a solution that works for me.

I've looked at every article I can find on it on scriptinghelpers and devforum and I just can't seem to fix anything.