Pathfinding NPC stutters and rotates randomly while following Player, how to solve?

Hi guys, Tophat here.

I am trying to make an NPC follow the player’s character. The good news is that it works, in terms of the NPC going to the player.

However, it randomly stutters and jerks its rotation to the side for some reason. I am not sure how to tackle this problem.

This is the code in a server script, located inside the NPC (edited to exclude unnecessary sections)

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local PathfindingService = game:GetService("PathfindingService")
local Waypoints = nil

Players.ChildAdded:Connect(function(Player)
	local Character = Player.CharacterAdded:Wait()
	local Humanoid = Character:WaitForChild("Humanoid")
	local RootPart = Character:WaitForChild("HumanoidRootPart")
	
	RunService.Heartbeat:Connect(function()
		local Path = PathfindingService:CreatePath()
		local success, errorMessage = pcall(function()
			Path:ComputeAsync(script.Parent.HumanoidRootPart.Position, RootPart.Position)
		end)
		if success and Path.Status == Enum.PathStatus.Success then
			Waypoints = Path:GetWaypoints()
			for i, v in pairs(Waypoints) do
				script.Parent.Humanoid:MoveTo(v.Position)
				script.Parent.Humanoid.MoveToFinished:Wait(10)
			end
		end
	end)
end)

NOTE: The way I used Players.ChildAdded is intentional, since it’s a singleplayer game. I am aware that this script may break when the character dies, I know how to deal with that event.

Here is a video showing the pathfinding work, but has the NPC rotates randomly while it does that:

I could use a little help here, what should I do to fix this? Manually change the NPC’s orientation? Using something else other than RunService.Heartbeat?

Thanks!

1 Like

i don’t quite remember what HeartBeat is for, but it’s probably not the best in this scenario. you should change :MoveToFinished(10) to :MoveToFinished(). also try adding this to your script:

for i,part in pairs(Character:GetChildren()) do
if part:IsA(‘BasePart’) then
part:SetNetworkOwner() --this may reduce lag a little
end
end

1 Like

So I’ve changed .MoveToFinished:Wait() to what you’ve said, and I’ve also just decided to visualize the waypoints, and, oh…

I’ve accidentally created a ton of paths because I was using HeartBeat (by the way, this is an event that fires every frame)

I want to limit this to just 1 path, but it constantly updates so that the NPC can follow me constantly without having to pause for too long, if possible.

If I just use a while loop, it pauses extreme visibly.

you need to add cooldown/update path if it already exists (while loop is good for this)

For this, i think you need to do two things

  1. Add a cooldown for the path update
RunS.Heartbeat:Connect(function()
	local number = 1 --Waiting time for update
	local count = 0
	local countWait = number * 6 --6 because Heartbeat runs 60 frames per second (Divided by 10 so it can support decimals)

	if count <= countWait then
		count += 0.1
	else
		if count >= countWait then
			count = 0
			--Calculate the path
		end
	end
end)
  1. Add a separate heartbeat fuction (or connect it with the above one), so when there is just 2 waypoints, it starts just following the target instead of the waypoints (prevents it from stopping from time to time, recommended to large up waypoint spacing)
RunS.Heartbeat:Connect(function()
	local waypoints = path:GetWaypoints()
	if #waypoints == 2 then
		hum:MoveTo(target.Position)
	end
end)