Laggy pathfinding

Ive been trying to fix this pathfinding code for the past 5 weeks and have re-written the code 6 times, yet I cant seem to get it to work. Here’s what its looking like:


As you can see, when it is wandering, it works absolutely flawlessly. However, whenever I become the target, this happens:

As the red spheres indicate, it is calculating the path fine still, but it wont follow it, except rarely for a really short period of time, really slowly.

Here’s my code:

-- main functions
local function followPath()
	pathIsRunning = true
	while true do
		if ind >= #waypoints - 1 then
			onTargetReached()
			local w = waypoints
			repeat wait() until w ~= waypoints
			continue
		end
		
		if waypoints[ind].Action == Enum.PathWaypointAction.Jump then
			humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
		end
		humanoid:MoveTo(waypoints[ind].Position)
		ind += 1
		print(ind)
		humanoid.MoveToFinished:Wait()
		
	end
end

local function calcPath(targetPos: Vector3): nil	
	local success, errorm = pcall(function()
		path:ComputeAsync(ghostRoot.Position, targetPos)
	end)
	
	if success then
		waypoints = path:GetWaypoints()
		updatePoints()
		
		if #waypoints <= 2 then
			onTargetReached()
			return
		end
		
		local bestWaypoint: number = 1
		local bestDist: number = distSquared(waypoints[1].Position, ghostRoot.Position)
		local secondBestWaypoint: number = 2
		local secondBestDist: number = distSquared(waypoints[2].Position, ghostRoot.Position)
		
		if secondBestDist < bestDist then
			local temp = {bestWaypoint, bestDist}
			bestWaypoint = secondBestWaypoint
			bestDist = secondBestDist
			secondBestWaypoint = temp[1]
			secondBestDist = temp[2]
		end
		
		for i = 3, #waypoints, 1 do
			local wp = waypoints[i]
			local dist: number = distSquared(wp.Position, ghostRoot.Position)
			if dist < bestDist then
				secondBestDist = bestDist
				secondBestWaypoint = bestWaypoint
				bestDist = dist
				bestWaypoint = i
			elseif dist < secondBestDist then
				secondBestDist = dist
				secondBestWaypoint = i
			end
		end
		
		ind = math.max(secondBestWaypoint, bestWaypoint)
		
		if not pathIsRunning then
			followPath()
		end
	else
		warn("Error while computing path: "..errorm)
		lastPathTarget = nil
	end
end

I also have some code that will run calcPath every 0.2 seconds with a new place to go to. I will send this if requested. followPath is only called once as the pathIsRunning flag suggests. I know its not lag because here are the script analytics taken from the developer console in game:


I have tried spacing out the waypoints further, increasing the delay between path calculations, but nothing works. Does anyone have any idea as to what is going wrong?

Thanks for any help!

1 Like

Try putting this in a script somewhere in the Model

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

(Sorry for the bump)

I tried setting network owner, it didnt work

theres a couple of ways to fix it, use the script @TheSai_ki sent, but SetNetworkOwner() to nil so the server has ownership. also, define some pathfinding settings for your path, such as spacing out the nodes so they’re not as clumped together.

2 Likes

Its probably the fact you’re trying to calculate path every 0.2 second, which is very unnecessary.

Instead of this - wait until the player’s position has moved x distance away from its lastKnownPosition and then calcPath again.

local lastKnownPosition = player.Position

while true do
   if (lastKnownPosition == nil or (lastKnownPosition - player.Position).Magnitude > 10) then
       lastKnownPosition = player.Position
       calcPath(...)
   end
   wait(0.5)
end

As a note to the above replies - Setting the Network Owner is only relevant to physics and updating a part on the client, rather than the server.

On a separate note - what does your onTargetReached method do? Its referenced twice in the above code but not stated.

you are calculating the path way too many times and calculating ones when you dont need to

only calculate the path once the target moved away from the path using 0.2-0.5 studs away

instead of passing the target’s position pass the part of that position so you can get the updated position and do those distance checks

make sure you dont call anything while the npc is moving to a point (moveToFinish should yield everything) if your points are close enough (but not too close like what your video shows, points are way too close) moveToFinish wont yield for long

if you lost your target (moved away/died/etc) break the waypoints loop and calculate a new path

That’s kind of what you do to constantly update the NPC’s Pathfind

As I said, lag was not the issue. I found out the issue was with humanoid.MoveToFinished. It seemed like it was firing way too long after it should have. This is likely an issue on roblox’s end, but what I ended up doing was making my own movement system. As for my game I don’t need the monster to jump, so I managed to just get away with using a raycast to find the ground surface and just tween the monster position, throwing out roblox’s movement system entirely. That did the trick and now everything works perfectly!

1 Like

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