[UNSOLVED] Pathfinding is lagging and stuttering

I have a Baldi NPC that always goes to the players location. I’ve tried so many things, and yet, Baldi keeps stuttering and lagging. How do I fix this? Here’s the code and the example.

local Pathfinding = game:GetService("PathfindingService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local path = Pathfinding:CreatePath({
	AgentHeight = 2;
	AgentRadius = 0.1;
	AgentCanJump = false;

	Costs = {
		Water = 100;
		DangerZone = math.huge
	}
})

local Character = script.Parent
local humanoid = Character:WaitForChild("Humanoid")

local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection

local function findTarget()
	local maxDistance = 10000  --The farest away distance that the "Zombie" starts to follow a player
	local nearestTarget

	for index, player in pairs(Players:GetPlayers()) do
		if player.Character then
			local target = player.Character
			local distance = (Character.HumanoidRootPart.Position - target.HumanoidRootPart.Position) .Magnitude

			if distance < maxDistance and target.Humanoid.Health > 0 then
				nearestTarget = target
				maxDistance = distance
			end

			if distance < 4 and nearestTarget then
				nearestTarget.Humanoid:TakeDamage(100)
			end
		end
	end

	return nearestTarget
end

local function followPath(destination)

	local success, errorMessage = pcall(function()
		path:ComputeAsync(Character.PrimaryPart.Position, destination)
	end)

	if success and path.Status == Enum.PathStatus.Success then
		waypoints = path:GetWaypoints()

		blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
			if blockedWaypointIndex >= nextWaypointIndex then
				blockedConnection:Disconnect()
				followPath(destination)
				return
			end
		end)

		if not reachedConnection then
			reachedConnection = humanoid.MoveToFinished:Connect(function(reached)
				if reached and nextWaypointIndex < #waypoints then
					nextWaypointIndex += 1
					humanoid:MoveTo(waypoints[nextWaypointIndex] .Position)
				else
					reachedConnection:Disconnect()
					blockedConnection:Disconnect()
					return
				end
			end)
		end

		nextWaypointIndex = 2
		humanoid:MoveTo(waypoints[nextWaypointIndex] .Position)
	else
		warn("path not found")
		return
	end
end

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

while task.wait() do
	local target = findTarget()
	if target then
		followPath(target.HumanoidRootPart.Position)
	end
end

I see a few problems. I’ll list them here

  1. In your findtarget() function, it should be local distance = (target.HumanoidRootPart.Positoin - Character.HumanoidRootPart.Position.Magnitude
  2. It would be better to leave the network owner for the baseparts to default as setting their owner to nil results in “jittery physics interactions for the client”

i did the first one and everything was fine, but after doing the second one i think everything just got worse :frowning:

Ok then revert it back to nil. I got the second one from the docs. May I ask why you’re setting it to nil?

I heard that it would make it less laggy, and it does pretty much that. However, the AI still stutters, because it occasionally stops moving for half a second after every waypoint before moving to the next one.

Imo, the Roblox docs example is just so unoptimised. I would completely rewrite it. There’s no point in having a reached connection. So I’ll guide you to make your own, more optimized pathfinding.

  1. Make your pathfinding logic in a module script, keeps it nice and simple
  2. Have a function to target the player (You’ve already made it so nice :+1: )
  3. (Optional) Check if Baldi can see the player with his eyes using raycasting
  4. Make a function to target the player. You can frame it like this
function PathfindingModule.TargetPlayer(target)
   local path
   local wi = 0
   local s,e = pcall(function()
      -- Compute a path here
   end)
   if path.Status == Enum.PathStatus.Success then
       local waypoints = -- Get waypoints from path
       for i, waypoint in pairs(waypoints) do
          -- Move your character
          wi = i
          Character.MoveToFinished:Wait() -- This is a better alternative to the goofy reachedconnection
       end
       path.Blocked:Connect(function(bi)
          -- Code here to check if path ahead is blocked
       end)
   else
      warn('Path failed,retrying')
      TargetPlayer()
   end
end

I practically have almost no idea how to make pathfinding, so this is gonna take me a while… That’s why I used the Documentation. So I’m not really sure what to do. This looks way different than what the Documentation shows. But I can try.

If you want me to, I can teach you step by step via other communication means, or you could watch a YouTube video

Are you able to do it in DevForum PMs?

Yeah sure shdhdhdhdbeueuurd