Why is my NPC walking kind of "stuttering"? Like, it walks a little and then stops

I’m having a problem with pathfinding, and i dont know how to fix it :confused:

Script:

local npc = script.Parent
local humanoid = npc:FindFirstChild("Humanoid")
local initialPosition = npc.PrimaryPart.Position
local randomWalkRadius = 0 -- Raio de andar aleatoriamente
local detectionRadius = 50 -- Raio de detecção do jogador
local followRadius = 50 -- Raio máximo para seguir o jogador
local canJump = true -- Define se o NPC pode pular ou não
local CanNotWalkInPublic = true
local pathfindingService = game:GetService("PathfindingService")
local randomMoveWaitTimeMin = 1
local randomMoveWaitTimeMax = 10

-- Verifica se o jogador está olhando para o NPC
local function isPlayerLooking(player)
	if not CanNotWalkInPublic then return false end -- Se WalkInPublic for falso, ignora essa verificação
	local playerRootPart = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
	if playerRootPart then
		local npcDirection = (npc.PrimaryPart.Position - playerRootPart.Position).Unit
		local playerLookDirection = playerRootPart.CFrame.LookVector
		local dotProduct = npcDirection:Dot(playerLookDirection)
		return dotProduct > 0.5
	end
	return false
end


-- Ancorar ou desancorar todas as Parts do NPC
local function setNPCAnchored(state)
	for _, part in ipairs(npc:GetDescendants()) do
		if part:IsA("BasePart") then
			part.Anchored = state
		end
	end
end

-- Movimento aleatório
function moveRandomly()
	local retries = 0
	local moved = false
	while not moved and retries < 5 do
		local targetPosition = initialPosition + Vector3.new(
			math.random(-randomWalkRadius, randomWalkRadius),
			0,
			math.random(-randomWalkRadius, randomWalkRadius)
		)
		local path = pathfindingService:CreatePath({
			AgentCanJump = canJump,
			AgentJumpHeight = humanoid.JumpHeight,
			AgentMaxSlopeAngle = humanoid.MaxSlopeAngle
		})
		path:ComputeAsync(npc.PrimaryPart.Position, targetPosition)
		local waypoints = path:GetWaypoints()
		if #waypoints > 0 then
			for _, waypoint in ipairs(waypoints) do
				humanoid:MoveTo(waypoint.Position)
				if waypoint.Action == Enum.PathWaypointAction.Jump then
					humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
				end
				humanoid.MoveToFinished:Wait(math.random(randomMoveWaitTimeMin, randomMoveWaitTimeMax))
				moved = true
			end
		end
		retries = retries + 1
	end
end

-- Seguir jogador
function followPlayer(player)
	local playerRootPart = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
	if playerRootPart then
		local path = pathfindingService:CreatePath({
			AgentCanJump = canJump,
			AgentJumpHeight = humanoid.JumpHeight,
			AgentMaxSlopeAngle = humanoid.MaxSlopeAngle
		})
		path:ComputeAsync(npc.PrimaryPart.Position, playerRootPart.Position)
		local waypoints = path:GetWaypoints()
		if #waypoints > 0 then
			for _, waypoint in ipairs(waypoints) do
				if isPlayerLooking(player) then
					humanoid:MoveTo(npc.PrimaryPart.Position)
					setNPCAnchored(true)
					return
				else
					setNPCAnchored(false)
				end

				humanoid:MoveTo(waypoint.Position)
				if waypoint.Action == Enum.PathWaypointAction.Jump then
					humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
				end
				humanoid.MoveToFinished:Wait()
			end
		end
	end
end

-- Comportamento
function npcBehavior()
	while true do
		local closestPlayer = nil
		local closestDistance = detectionRadius

		for _, player in pairs(game.Players:GetPlayers()) do
			local playerRootPart = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
			if playerRootPart then
				local distance = (playerRootPart.Position - npc.PrimaryPart.Position).Magnitude
				if distance <= closestDistance then
					closestPlayer = player
					closestDistance = distance
				end
			end
		end

		if closestPlayer then
			if isPlayerLooking(closestPlayer) then
				setNPCAnchored(true)
				humanoid:MoveTo(npc.PrimaryPart.Position)
			else
				setNPCAnchored(false)
				followPlayer(closestPlayer)
			end
		else
			setNPCAnchored(false)
			moveRandomly()
		end

		wait(0.1)
	end
end

npcBehavior() 
2 Likes

I tried your code and did a quick search on the devforum, I found this post that shares the same problem as you with a solution that might help you Pathfinding NPC eventually coming to a stop (Waypoint iteration stopping?) - #3 by huh_crazy

1 Like

Replace npcBehaviour function with this:

local RunService = game:GetService("RunService")

function npcBehavior()
	RunService.Heartbeat:Connect(function()
		local closestPlayer = nil
		local closestDistance = detectionRadius

		for _, player in pairs(game.Players:GetPlayers()) do
			local playerRootPart = player.Character and player.Character:FindFirstChild("HumanoidRootPart")
			if playerRootPart then
				local distance = (playerRootPart.Position - npc.PrimaryPart.Position).Magnitude
				if distance <= closestDistance then
					closestPlayer = player
					closestDistance = distance
				end
			end
		end

		if closestPlayer then
			if isPlayerLooking(closestPlayer) then
				setNPCAnchored(true)
				humanoid:MoveTo(npc.PrimaryPart.Position)
			else
				setNPCAnchored(false)
				followPlayer(closestPlayer)
			end
		else
			setNPCAnchored(false)
			moveRandomly()
		end
	end)
end
npcBehavior()
1 Like

Step number 1, do not use movetofinished.
step number 2, use setnetworkownernil

Step number 2, here is your edited code.

local function setNPCAnchored(state)
	for _, part in ipairs(npc:GetDescendants()) do
		if part:IsA("BasePart") then
			part.Anchored = state
                        if state == false then part:SetNetworkOwner(nil) end
		end
	end
end

And for number 1.

humanoid:MoveTo(waypoint.Position)
if waypoint.Action == Enum.PathWaypointAction.Jump then
	humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
local precision = 6 --// change this to be smaller but big enough so he goes to waypoints
local dist = (npc.PrimaryPart.Position - waypoint.Position).Magnitude  
repeat task.wait() dist = (npc.PrimaryPart.Position - waypoint.Position).Magnitude until dist <= precision
3 Likes

Nevermind I misread part of the script

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.