PathfindingService keeps producing waypoints through obstacles

I’ve been scripting an npc for a game, I want the npc to be able to chase after players and not collide with obstacles when trying to find a path towards them. To solve this problem, I’ve utilized the use of PathfindingService, however I’ve encountered a few issues with it, mostly when the npc is in an enclosed room with no way out.
When I try to find a path from the npc’s position to the target position, I get waypoints that are clearly impossible to traverse, colliding with obstacles and walls, sometimes even going through the ceiling.
Here’s a video portraying the issue (the walls have been made transparent to make it easier to see the npc and the waypoints)

Ideally the Path’s status should equal to Enum.PathStatus.NoPath, however it’s instead Enum.PathStatus.Success, occasionally it does equal to NoPath but thats mostly due to the npc flinging around which isn’t the issue for now

I’ve tried using PathfindingModifiers but that has not been successful for me, as shown in the video.
The walls are union parts that have pathfinding modifiers inside of them, with an infinite weight assigned to them to prevent the npc from walking on the wedges that are part of it.

I’ve also messed around with the agent params and that doesn’t really change the results in any meaningful way.

I believe the code to be functionally sound but I have attached a snippet for clarification

local pathfinder = Pathfinder(
    npc,
    {
        AgentRadius = 3,
        AgentHeight = 4,
        AgentCanJump = true,
        AgentCanClimb = false,
        Costs = {
            Wall = math.huge,
            DontCross = math.huge
        }
    })

-- path instance is created in this manner
_path = PathfindingService:CreatePath(agentParams)
-- in the function for the pathfinder, that creates and generates the waypoints
self._path:ComputeAsync(self.npc:GetPivot().Position, target:GetPivot().Position)
local waypoints = self._path:GetWaypoints()
print(self._path.Status, #waypoints) -- Enum.PathStatus.Success most of the time

I’m at a loss on as to what to do to fix this issue, so any sort of help or pointers will be extremely helpful, please and thank you!

I’m not sure on this, but I think roblox has done some weird stuff to pathfinding as I’m getting near identical problems on my game.

Example of my own issue

On my game, the NPCs are decided to, instead of walk around an obvious obstacle, to walk right through it, which in the NavMesh, is clearly blocked.
My agents cannot jump, and yes I have not allowed jumping in the agent parameters.

1 thing you could try is first, check the navmesh.

If the navmesh appears to be correct but pathfinding is still doing this, create a bug report. There’s nothing you’re doing wrong, pathfinding just seems broken at the moment.

Is this using the new pathfindingImprovedSearch? also show the code on how the npc interacts with waypoints. we cant help without info

I checked the navigation mesh as you suggested, and this is what I found



It seems to have those blue planes underneath the wall, even though it should not be passable
I’ll investigate a bit more before trying to file a bug report, the issue might be how the hallway and room are constructed

1 Like

I’m not sure, this is the first time I’m hearing of such a property. It was set to Default before I checked, I tried setting it to disabled and it didn’t seem to help.
Here’s a more helpful snippet of the code

-- some constants
pathfinder._STOP_PATHFINDING_THRESHOLD = 5 -- studs, when the distance from the target character and the npc is less than this distance, it will assume that it has reached the target
pathfinder._TARGET_REACHED_THRESHOLD  = 5 -- studs, when the distance from the target waypoint and the npc is less than this distance, it will assume that it has reached the waypoint

function Pathfinder:_getCurrentGroundPosition()
    local rootCFrame = self.npc:GetPivot()
    local result = workspace:Raycast(rootCFrame.Position, -Vector3.yAxis * 10, self._groundRaycastParams)
    local groundPosition

    if result then
        groundPosition = result.Position
    else
        groundPosition = rootCFrame.Position
    end

    return groundPosition
end

function Pathfinder:_update(dt)
    local groundPosition = self:_getCurrentGroundPosition()
    local targetPosition = self._target:GetPivot().Position
    local rootCFrame = self.npc:GetPivot()
    local direction = (self.TargetPoint - groundPosition)
    local distance = (Vector3.new(1, 0, 1)*targetPosition - Vector3.new(1, 0, 1)*rootCFrame.Position).Magnitude
    if distance <= self._STOP_PATHFINDING_THRESHOLD then
        if not self._pathCompleted then
            self._pathCompleted = true
            self.OnPathFinished:Fire()
        end
        return
    end
    if self._pathCompleted then
        self:_updateTarget(self._target)
        return
    end
    if self.Jump then
        self.Jump = false
        if self.npc:FindFirstChild('Humanoid') then
            self.npc.Humanoid.Jump = true
        else
            self.OnJump:Fire()
        end
    end
    if direction.Magnitude <= self._TARGET_REACHED_THRESHOLD then
        if self:AdvanceToNextPoint() then
            self._pathCompleted = true
            self.OnPathFinished:Fire()
        else
            self.OnReachedPoint:Fire()
            return self:_update(dt)
        end
    else
        self.MoveToPositionUpdated:Fire(position)
    end
end

function Pathfinder:AdvanceToNextPoint()
    if #self._wayPoints == 0 then
        return true
    end
    local point = table.remove(self._wayPoints, 1)
    self.TargetPoint = point.Position
    self.Jump = point.Action == Enum.PathWaypointAction.Jump
    return false
end

function Pathfinder:_updateTarget(target)
    self._path:ComputeAsync(self.npc:GetPivot().Position, target:GetPivot().Position)
    local waypoints = self._path:GetWaypoints()
    self:AdvanceToNextPoint()
    if self:AdvanceToNextPoint() then
        return true
    else
        return false
    end
end


-- the npc uses this pathfinder object like this
pathfinder.MoveToPositionUpdated:Connect(function(position)
    npcController:MoveTo(position)
end)
pathfinder.OnJump:Connect(function()
    npcController:Jump()
end)

It is disabled by default, try enabling the improved pathfinding, it is quite better than the old one.

I did just that, unfortunately the issue still persists. It keeps finding waypoints through the wall somehow


image

Ok so that happens most likely because you call all the waypoints each frame, when your npc jumps is still calls your pathfinding and since the starting node is at top the npc keeps getting its first nodes at a different places.

What you should do is call the 3rd or 4th node of the pathfinding and moveTo it. if that doesnt work change waypointsDIstance.

Thank you, but unfortunately the issue isn’t that. My issue is that the waypoints are being generated, even though in this case its impossible for a path to exist from the npc to the target. I have tried experimenting with changing waypoints distance, but that didn’t help my case.

If this wasn’t already fixed, is that part a “WedgePart”?
image

WedgeParts and CornerWedgeParts cause issues for pathfinding since they’re outdated and end up being ignored by navigation, so you have to create a new part and change the shape to the “Wedge” or “CornerWedge” enum types to fix it.
image

It’s an age-old problem for pathfinding that was hidden in plain sight for a very long time that I just discovered today; I hope this solves your issue. :folded_hands:

3 Likes

Hi, I checked and it’s not a wedge part. It’s a UnionOperation part. I’ve made a bug report because of this over here, with a better video displaying the issue