NPC using pathfindingservice not working correctly

Hello,
I’m making a game like piggy and am currently making the AI for it. It works fine, but it Jitters. What I mean by this is, is if a player moves when the NPC is still walking, it still goes to their old position before going to their new one.
Video of what I mean:

https://gyazo.com/850a15a7ea4fad0710f296246fc9c770

Here is my script:

local pathservice = game:GetService("PathfindingService")
local runservice = game:GetService("RunService")
local players = game:GetService("Players")

local pathParams = {
	["AgentHeight"] = 20,
	["AgentRadius"] = 20,
	["AgentCanJump"] = true
}

local path = pathservice:CreatePath(pathParams)
local rand = Random.new(tick()%1*2e6)

local function WaitEvent(ev,t)
	local obj = Instance.new("BoolValue")
	local returns
	local c;c = ev:Connect(function(...)
		c:Disconnect()
		c = nil
		returns = {...}
		obj.Value = true
	end)
	do
		coroutine.wrap(function()
			local ti = tick()
			local waitTime = t
			while (tick()-ti < waitTime) do
				if (returns) then return end
				waitTime = t + runservice.Heartbeat:Wait()
			end
			if (returns) then return end
			c:Disconnect()
			obj.Value = true
		end)()
	end
	obj:GetPropertyChangedSignal("Value"):Wait()
	obj:Destroy()
	return (returns) and unpack(returns) or nil
end

local dir = Vector3.new(0,-4,0)

local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Blacklist
--params.FilterDescendantsInstances = {workspace.Zombies}

local function CheckSight(root,target)
	local dif = target.Position-root.Position
	local mag = dif.Magnitude
	
	local ray = Ray.new(root.Position,dif.Unit*mag)
	local p = workspace:FindPartOnRay(ray,root.Parent.Parent)
	
	if ((p) and (p:IsDescendantOf(target.Parent)) and (math.abs(target.Position.Y-root.Position.Y) < 3)) then
		if (mag <= 20) then
			local mid = root.Position:Lerp(target.Position,0.5)
			local p = workspace:Raycast(mid,dir,params)
			if (not p) then
				return false
			end
		else
			for i = 0.125,0.875,0.125 do
				local mid = root.Position:Lerp(target.Position,i)
				local p = workspace:Raycast(mid,dir,params)
				if (not p) then
					return false
				end
			end
		end
		--print("ey")
		return true
	end
	
	return false
end

for _,v in pairs(script.Parent:GetDescendants()) do
	if (v:IsA("BasePart")) then
		v:SetNetworkOwner()
	end
end

local jumpstates = {
	Enum.HumanoidStateType.Running;
	Enum.HumanoidStateType.RunningNoPhysics;
}

local function Jump(humanoid)
	local state = humanoid:GetState()
	if (not table.find(jumpstates,state)) then
		local c;c = humanoid.StateChanged:Connect(function(state)
			if (not table.find(jumpstates,state)) then return end
			c:Disconnect()
			c = nil
			humanoid.Jump = true
		end)
	else
		humanoid.Jump = true
	end
	return true
end

local function FindNearestPlayer()
	local plrs = players:GetPlayers()
	local nearPlr,near
	for i = 1,#plrs do
		local v = plrs[i]
		if ((v.Name ~= script.Parent.Name) and (v.Character) and (v.Character.Humanoid.Health > 0)) then
			local mag = (script.Parent.HumanoidRootPart.Position-v.Character.HumanoidRootPart.Position).Magnitude
			if (not near) then
				near = mag
				nearPlr = v.Character.HumanoidRootPart
			elseif (near > mag) then
				near = mag
				nearPlr = v.Character.HumanoidRootPart
			end
		end
	end
	return nearPlr
end

-- // Zombie Damage \\ --

local coolDown = {}

script.Parent.HumanoidRootPart.Touched:Connect(function(hit)
	if (hit.Parent.Name == script.Parent.Name) then return end
	local hum = hit.Parent:FindFirstChild("Humanoid")
	if ((not hum) or (coolDown[hum])) then return end
	coolDown[hum] = true
	hum:TakeDamage(10)
	wait(1)
	coolDown[hum] = nil
end)

---------------------------

while true do
	local root = FindNearestPlayer()
	if (root) then
		local isVisible = CheckSight(script.Parent.HumanoidRootPart,root)
		
		if (isVisible) then
			script.Parent.Humanoid:MoveTo(root.Position)
			wait()
		else
			path:ComputeAsync(script.Parent.HumanoidRootPart.Position,root.Position)
			if (path.Status == Enum.PathStatus.Success) then
				local wp = path:GetWaypoints()
				for i = 3,#wp do
					local v = wp[i]
					if (v.Action == Enum.PathWaypointAction.Jump) then
						Jump(script.Parent.Humanoid)
					end
					script.Parent.Humanoid:MoveTo(v.Position)
					local reached = WaitEvent(script.Parent.Humanoid.MoveToFinished,1)
					if (not reached) then
						--print("stuck!")
						Jump(script.Parent.Humanoid)
						break
					end
					if (CheckSight(script.Parent.HumanoidRootPart,root)) then
						script.Parent.Humanoid:MoveTo(root.Position)
						break
					end
					if ((root.Position-wp[#wp].Position).Magnitude >= 40) then
						if ((root.Position-script.Parent.HumanoidRootPart.Position).Magnitude <= 20) then
							script.Parent.Humanoid:MoveTo(root.Position)
						elseif (wp[i+1]) then
							script.Parent.Humanoid:MoveTo(wp[i+1].Position)
						end
						print("target moved")
						break
					end
				end
				wait()
			else
				--print("couldnt find path")
				script.Parent.Humanoid:MoveTo(root.Position)
				wait(0.1)
			end
		end
	else
		wait()
	end
end

Thanks for any help!

I’d like to politely ask you to re-read my post.

I clearly mentioned that I know that, however the npc is slow to react. When I climb through the window, it moves to my old position, before I moved through the window, this also happens when I turn or my position moves, it’s not instant.

I kinda carefully skimmed through the script, and noticed this ^^

Does that effect your movement?

Tried removing that, but it didn’t work.

Here is a better gif: https://gyazo.com/4c883e3e3bcc568eefa5d07ed301a5ee

As you can see, it’s slow to turn.

I’d recommend making the NPC only explore a third (or two thirds) of its path before calculating a new one. It is somewhat less efficient, but it should help avoid the jittering problem when it chases players who actively try to avoid it by taking less than trivial courses.