Pathfinding AI stuttering

Heya there.

I’m working on a pathfinding module for my game and as the title says, it’s stuttering for whatever reason.

--[[SERVICES]]--
local Players = game:GetService("Players")
local PathfindingService = game:GetService("PathfindingService")
local RunService = game:GetService("RunService")

--[[MODULE]]--
local PathfindingModule = {}

function PathfindingModule.Pathfind(NPC, AggroRange)
	--//Preperation Variables
	local Rootpart = NPC.PrimaryPart
	local Humanoid = NPC:FindFirstChildWhichIsA("Humanoid")
	local CharacterSize = NPC:GetExtentsSize()
	local Objective = workspace:WaitForChild("Crystal")
	
	Rootpart:SetNetworkOwner(nil)
	
	--//PathfindingAgents
	local PathfindingAgents = {
		AgentRadius = (CharacterSize.X + CharacterSize.Z)/4,
		AgentHeight = CharacterSize.Y,
		AgentCanJump = true
	}	
	
	local function FollowPath(Destination)
		local Path = PathfindingService:CreatePath(PathfindingAgents)
		Path:ComputeAsync(Rootpart.Position, Destination)
		if Path.Status == Enum.PathStatus.Success then
			local Waypoints = Path:GetWaypoints()
			local Markers = {}
			
			for _, Waypoint in pairs(Waypoints) do
				if Waypoint.Action == Enum.PathWaypointAction.Jump then
					Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
				end
				
				Humanoid:MoveTo(Waypoint.Position)
				Humanoid.MoveToFinished:Wait(2)
			end
			
			for _, Maker in pairs(Markers) do
				Maker:Destroy()
			end
			
		else
			warn("NPC got stupid and forgot how to pathfind, sorry!")
		end
	end
	
	local function FindNearestPlayer()
		local NearestPlayer = nil
		local ClosestDistance = AggroRange
		local PlayerList = Players:GetPlayers()
		
		for _, Player in pairs(PlayerList) do
			local Character = Player.Character or Player.CharacterAdded:Wait()
			local Humanoid = Character:FindFirstChildWhichIsA("Humanoid")
			
			if Character and Humanoid.Health > 1 then
				local Distance = (Character.PrimaryPart.Position - Rootpart.Position).Magnitude
				if Distance < ClosestDistance then
					ClosestDistance = Distance
					NearestPlayer = Character
				end
			end
		end
		return NearestPlayer
	end
	
	RunService.Heartbeat:Connect(function()
		local Target = FindNearestPlayer()
		
		if Target then
			Objective = Target
		else
			Objective = workspace:FindFirstChild("Crystal")
		end
		
		if Objective and Objective.PrimaryPart then
			FollowPath(Objective.PrimaryPart.Position)
		end
	end)
end

return PathfindingModule

A few things you can add… wait(2) is a bit harsh.
Some snippets, I’m sure your settings will be different.

local H,dotSpace=math.huge,10
local Agents={WaypointSpacing=(dotSpace),
	AgentRadius=(4),AgentHeight=(4),
	AgentCanJump=(true),AgentCanClimb=(false),
	Costs={Metal=H,Basalt=H,LeafyGrass=H,SmoothPlastic=H}
}

for i, waypoint in ipairs(waypoints) do
		local distance = (waypoint.Position - PrimaryPart.Position).Magnitude
		local duration = (distance / (Humanoid.WalkSpeed * 1.033)) --finetune
		Humanoid:MoveTo(waypoint.Position)
		table.remove(waypoints, i)
        --my waypoints can have "dot" parts (error checking option)
		if (showPath) then removeDot(i) end 
		task.wait(duration)

Also for: Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
I think you can just do: Humanoid.Jump=true

Wow, okay.
But how would I implement this code into the module?

This one uses WaypointSpacing, WalkSpeed with duration as kind of fine-tuning.
Don’t really need the showPath thing. There is enough script there to see how to use it.
Your way of looping waypoints is fine, don’t need a table like this is doing.

1 Like

Apart from changing the wait, use
PrimaryPart:SetNetworkOwner(nil)