Pathfinding edge case

I have a very specific need for pathfinding… What I want is for an NPC is attempt to go to a destination point (duh), but to be able to make the NPC, if faced with a door marked as impassable, halt near it; Like wait patiently until the door is marked as passable again.

This is a script I have so far, I stress tested it for 10min with doors that alternated between having a blocked tag and not with the script checking, and while it mostly worked, the rig did walk through a blocked door once.

Any ideas on a reliable way I could do this?

(Ignore the spaghetti I used for alternating the destination it works and thats all I care about rn)

local turn = true

while true do

	local PathfindingService = game:GetService("PathfindingService")
	local CollectionService = game:GetService("CollectionService")

	local rig = script.Parent

	local destination
	if turn then
		destination = workspace.Destination
	else
		destination = workspace.Destination2
	end

	turn = not turn

	local blockedTag = "Blocked"
	local waypoints = {}

	-- Function to check if a waypoint is inside or too close to a blocked part
	local function isWaypointBlocked(waypoint)
		for _, part in ipairs(CollectionService:GetTagged(blockedTag)) do
			local distance = (waypoint.Position - part.Position).Magnitude
			if distance <= (part.Size.Magnitude / 2.1) then
				return true
			end
		end
		return false
	end

	-- Function to move the rig along the waypoints
	local function moveRig()
		for _, waypoint in ipairs(waypoints) do
			if not isWaypointBlocked(waypoint) then
				rig.Humanoid:MoveTo(waypoint.Position)
				rig.Humanoid.MoveToFinished:Wait()
			else
				return false -- Return false to indicate the path is obstructed
			end
		end

		-- Move directly to the destination at the end
		rig.Humanoid:MoveTo(destination.Position)
		rig.Humanoid.MoveToFinished:Wait()
		return true
	end

	-- Function to calculate a path to the destination
	local function calculatePath()
		local path = PathfindingService:CreatePath({
			AgentRadius = 2,
			AgentHeight = 5,
			AgentCanJump = false,
			AgentJumpHeight = 0,
			AgentMaxSlope = 45
		})

		path:ComputeAsync(rig.PrimaryPart.Position, destination.Position)
		if path.Status == Enum.PathStatus.Success then
			waypoints = path:GetWaypoints()
			return true
		else
			warn("Failed to calculate path")
			return false
		end
	end

	-- Main logic to navigate the rig
	local function navigateToDestination()
		while true do -- Loop indefinitely until the destination is reached
			if calculatePath() then
				local success = moveRig()
				if success then
					break
				end
			end
			task.wait(0.1) -- Wait before retrying
		end
	end

	-- Start navigation
	navigateToDestination()

end

I would try using PathfindingLinks. They allow more advanced control over paths with custom costs and functions.
For this problem in specific, you could define a UseDoor() function that checks if a door is open and walk through it, or to wait until it becomes open.
Good luck!

1 Like

Oh wow! In all my research that never came up. Ill play around with it when I can, thank you!