Pathfinding doesn't work if it's too far

it’s clear that it’s due to roblox’s pathfinding service issues but im wondering if there are any workarounds around this. If you guys have modules i could use, or advice. then that’d be great because i’ve been trying to fix it.

function SCP_096:ComputeSmartPath(startPos, targetPos)

	local success, err = pcall(function()
		self.Path:ComputeAsync(startPos, targetPos)
	end)

	if success and self.Path.Status == Enum.PathStatus.Success then
		return self.Path
	else
		warn("Direct path failed:", err)
		return nil
	end
end

this is just it for the computing

2 Likes

Try generating partial paths with workspace.PathfindingUseImprovedSearch enabled.


tysm i never knew this existed. i enabled it but the path still returns nil, but it definetely improved the range though (i can get a little more farther for it to activate)- As i read through it i thought using partial path would do

PathSettings = {
SupportPartialPath = true
}

but still nope-

Path = PathfindingService:CreatePath({
			AgentRadius = 4,
			AgentHeight = 7,
			WaypointSpacing = 5,
			AgentCanClimb = false,
			AgentCanJump = false,
			Costs = {
				Floor = 1
			},
			
			PathSettings = {
				SupportPartialPath = true
			}
		}),
function SCP_096:ComputeSmartPath(startPos, targetPos)

	local success, err = pcall(function()
		self.Path:ComputeAsync(startPos, targetPos)
	end)

	if success and self.Path.Status == Enum.PathStatus.Success then
		return self.Path
	else
		warn("Direct path failed:", err)
		return nil
	end
end

is there anything im doing wrong?

This might just be an engine limitation then, can you try breaking it down to smaller intermediate waypoints towards the target?

Yeah i tried that, but the thing is it’s a little complicated because the map is a maze. I scrapped it because it was impossible due to the map (for me).

Do you know any pathfinding modules that support long distances?

You can break your map up into zones, then you can manually mark the entrances/exits for each one, and use a basic algorithm to find which entrance/exit to pathfind to.

Wait that is actually genius i didn’t think of that. I’ll try that!

err will be nil most of the time, because :ComputeAsync practically never throws errors.

You should change this line to:

warn("Direct path failed:", err or self.Path.Status)

If it finds a Partial Path, the Path Status will be ClosestNoPath, which you are not checking in the second code snippet you sent.

2 Likes

Oops, forgot about that! Yeah you’ll need to check for that status.

Thank you for the corrections i didn’t see that. i applied it now and yeah no matter how far i get, the path computes but it’s very buggy and just runs into the wall-. It says it’s deprecated too- i really don’t wanna invest alot of time in making an algorithm is there any more suggestions please i appreciate everything.

That’s a mistake that they still have not fixed for the Documentation for ClosestNoPath

3 Likes

Not sure if this is ACTUALLY a good way to script this but hey it works! :sob:

thank you for this idea. I hope roblox improves it alot more

I just manually created points around the map, and see if both the player and the NPC can pathfind to that point and store them inside the Meetable points folder. if there are multiple points- then i made it so that those points have a cost so that the npc can choose which to go to.

I’m still new and learning and i accept that this may be not the most efficient way of coding this algorithm but it lowk works. i’m open to critiques!

local MeetablePoints = {}

local PlayerPath = PathfindingService:CreatePath({
	AgentRadius = 2,
	AgentHeight = 5,
	WaypointSpacing = 5,
	AgentCanClimb = false,
	AgentCanJump = false,
})

local SCPPath = PathfindingService:CreatePath({
	AgentRadius = 4,
	AgentHeight = 7,
	WaypointSpacing = 5,
	AgentCanClimb = false,
	AgentCanJump = false,
})
function SCP_096:FindComputableEntrance(SCPStartPos)
	for _, Point in Points:GetChildren() do
		
		local PlrSuccess = pcall(function()
			PlayerPath:ComputeAsync(self.TARGETS[1].Character.HumanoidRootPart.Position, Point.Position)
		end)

		local SCPSuccess = pcall(function()
			SCPPath:ComputeAsync(SCPStartPos, Point.Position)
		end)
		
		if PlayerPath.Status == Enum.PathStatus.Success and SCPPath.Status == Enum.PathStatus.Success then
			local cost = (#SCPPath:GetWaypoints() * 1.5 + #PlayerPath:GetWaypoints() * 0.5)
			if not MeetablePoints[Point] then
				print("Path successful!")
				MeetablePoints[Point] = cost
			end
		else
			warn("Path Failed:", PlayerPath.Status, SCPPath.Status)
		end
	end
	
	print(MeetablePoints)
	local function GetLowestCost()
		local LowestVal = math.huge
		local LowestPoint = nil

		for Point, Cost in MeetablePoints do
			if Cost < LowestVal then
				LowestVal = Cost
				LowestPoint = Point
			end
		end

		return LowestPoint
	end

	local LowestPoint = GetLowestCost()

	if not LowestPoint then
		warn("No reachable intermediate point found.")
		return nil
	end

	-- Compute final path to lowest cost point
	local FinalPath = PathfindingService:CreatePath({
		AgentRadius = 4,
		AgentHeight = 7,
		WaypointSpacing = 5,
		AgentCanClimb = false,
		AgentCanJump = false,
		Costs = {
			Floor = 1
		},
	})

	local success = pcall(function()
		FinalPath:ComputeAsync(SCPStartPos, LowestPoint.Position)
	end)

	if FinalPath.Status == Enum.PathStatus.Success then
		print("Success")
		
		table.clear(MeetablePoints)
		return FinalPath
	else
		warn("Final path to selected point failed:", FinalPath.Status)
		return nil
	end
end

You should get the zone the target is in, then use an algorithm to connect zones and figure out which one leads to the target’s zone.