NPC stuttering regardless of Network Ownership when pathfinding

My code is pretty simple, I’m using the SimplePath module by V3NOM_Z. However, I encounter this issue even when I’m using my own implementation or the devforum’s implementation of pathfinding.

The npc stops for a fraction of a second at every waypoint.

This issue does not occur in studio, I’ve tried adjusting network ownership, checking network ownership, less-frequently updating, and a plethora of other adjustments with animations.

Code:

function Default:Path(user)
	if not self.pathing then
		self.pathing = true	
		
		for _, oldPathConnection in ipairs (self.pathConnections) do
			oldPathConnection:Disconnect()
		end

		local userCharacter = user.Character
		if not userCharacter then return end
		local humanoidRootPart = userCharacter:FindFirstChild("HumanoidRootPart")
		if not humanoidRootPart then return end
		
		for _, k in ipairs (self.instance:GetChildren()) do
			if k:IsA("BasePart") then
				print(k:GetNetworkOwner()) -- prints nil
			end
		end

		table.insert(self.pathConnections, self.path.WaypointReached:Connect(function()
			self.path:Run(humanoidRootPart.Position)
		end))

		self.path:Run(humanoidRootPart.Position)
	end
end
3 Likes

The Solution is :
Handling the animaton on the server

This is outdated but no, everything is already handled on the server in relation to the NPC.

Sorry for the very late reply you misunderstood what I meant
you should use an animator this is the way to run animations on the server side dont use Humanoid:LoadAnimation just use a server script and Animator:LoadAnimation
This will fix your problem.

related link

Yes, this wasn’t using humanoid as an animator, unless I’m missing what you’re saying, this is using an Animator and is unrelated to the animations.

There can be many reasons for stuttering let me address one of them

npc.humanoid:MoveToFinished:Wait() -- This can cause the npc animation stuttering
while (npc.HumanoidRootPart.Position - waypoint.Position).magnitude > 5 do -- Use this
    wait(0.1)
end

i hope this gonna fix your problem if you are sure the problem not from animations

If you’re still having issues with this you can check out this short tutorial I’ve made which doesn’t use any while loops, it solved the issues I had with npcs having stuttering walk animations

lol i used this solution as my starting point: Pathfinding jittery/stuttering walk animation solution,

my solution is below my npc has a field called isPathfinding that is pretty much the same as the path’s status field:

local isWalkPlaying = false -- Used to make sure the walk animation doesn't play on loop because Running fires many times with Pathfinding.

hum.Running:Connect(function(speed)
	print("Pathfinding status: ", self.isPathFinding)
	print("NPC Walking status: ", isWalkPlaying)
	print("NPC Speed is: ", speed)
	if speed > 0 and self.isPathFinding == "Active" then
		if isWalkPlaying == false then
			enemyAnimation["Walk"]:Play()
			enemyAnimation["Idle"]:Stop()
			isWalkPlaying = true
		end
		
	elseif speed <= 0 and self.isPathFinding == "Idle" then
		enemyAnimation["Idle"]:Play()
		enemyAnimation["Walk"]:Stop()
		isWalkPlaying = false
	end
end)

local path = PathService.new(enemy)
path.Visualize = true
-- Compute a new path every time the Dummy reaches the goal part
path.Reached:Connect(function()
	self.nearestCharacter = path.GetNearestCharacter(root.Position)

	local targetRoot = self.nearestCharacter:FindFirstChild("HumanoidRootPart")
	if targetRoot then
		if (root.Position - targetRoot.Position).magnitude <= self.attackRange then
			enemyAnimation["Attack"]:Play()
			enemyAnimation["Attack"].Stopped:Wait() 
		end
	end

	path:Run(self.nearestCharacter.HumanoidRootPart)
	self.isPathFinding = path._status

end)

-- Dummy knows to compute path again if something blocks the path
path.Blocked:Connect(function()
	self.nearestCharacter = path.GetNearestCharacter(root.Position)
	path:Run(self.nearestCharacter.HumanoidRootPart)
	self.isPathFinding = path._status

end)

-- If the position of Goal changes at the next waypoint, compute path again
path.WaypointReached:Connect(function()
	self.nearestCharacter = path.GetNearestCharacter(root.Position)
	path:Run(self.nearestCharacter.HumanoidRootPart)
	self.isPathFinding = path._status

end)

-- Dummmy knows to compute path again if an error occurs
path.Error:Connect(function(errorType)
	self.nearestCharacter = path.GetNearestCharacter(root.Position)
	path:Run(self.nearestCharacter.HumanoidRootPart)
	self.isPathFinding = path._status

end)

self.nearestCharacter = path.GetNearestCharacter(root.Position)
path:Run(self.nearestCharacter.HumanoidRootPart)
self.isPathFinding = path._status