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