For some reason, PathFindingService is making my NPCs walk up the stairs to the second floor above where they’re supposed to go instead of walking to the place on the first floor where they’re supposed to. Is there any way to exclude the stairs or something from being created in a path?
How does that look like? Can you take a screenshot of the 2nd and 1st floor? So we have a little bit more of context.
They come through this door and walk up the stairs, and then over where two of the registers are located which I screenshotted below.
What I want them to do is just walk directly through the door and to the registers.
Is there a invisible barrier not letting the NPC get to the balcony?
There aren’t any barriers. This is what the path from the door to the registers directly should look like.
If you can, record the NPC going towards that one spot. If you can’t, take a screenshot of the spot where the NPC stops moving. Please.
I have it set to automatically teleport them to the register once they’ve completed all of the waypoints in case they get stuck somehow, so it teleports them down to the register anyways, but it would look a lot better if it walked directly to the register.
That’s more than strange… It seems that the NPC prefers the longer way to get to the balcony, no idea what might be the issue. Would you mind showing the piece of code which uses PathFindingService to get the NPC to the balcony?
local path = PathFindingService:CreatePath()
path:ComputeAsync(randomNpc.HumanoidRootPart.Position, WalkTo.Position)
local waypoints = path:GetWaypoints()
for i,v in pairs(waypoints) do
if v.Action == Enum.PathWaypointAction.Jump then
humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
end
humanoid:MoveTo(v.Position)
humanoid.MoveToFinished:Wait()
end
randomNpc.HumanoidRootPart.CFrame = WalkTo.CFrame
WalkTo is an invisible part directly in front of the register. (sorry for the bad formatting this was far down in the code and i copied it weirdly)
Make sure the point at which they are supposed to arrive (WalkTo, whatever that is) is in the correct place, anchored, etc. If it’s not that, are there ANY PARTS that would be blocking their path? This seems like a group game, so maybe a group part that stops people not in the group from going into that area?
Checked and there aren’t any invisible walls.
I didn’t seem to find any possible solution. Can you do a test by making the NPCs appear at a closer spot to the balcony? Sorry for pretty much wasting your time…
There don’t need to be any walls or barriers, the problem happens with the pathfinding service itself. You see you can’t call/make a path using CFrame, so the NPC is walking towards a position and it will take the quickest path to that position. BUT the NPC / humanoid doesn’t know care about the Y axis position so it will just go to the stairs. I suggest moving the stairs or not having pathfinding at all, just add some waypoints and walk to the waypoints instead of the pathfinding!
Since the registers are only on one floor, could I just set the Y value to the Y value where the waypoints are on the first floor?
No, even if you do set a Y axis then it wont work. You have set the path’s Ending point’s position to and Y axis is also part of the position.
Consider creating an invisible barrier around the stairs in a separate CollisionGroup that can collide with players but not with NPCs. Assuming collisions are taken into account when creating the navmesh, NPCs won’t be able to generate a path through said block and they’ll be forced to determine a path at the current level they’re on.
Okay. I’ll just get a builder to move the stairs to somewhere else that looks nice. Thanks for the help.
That was my original idea but I haven’t gotten to testing it out yet. I’ll try putting an invisible block around the stairs with a collision group for NPCs so that they can’t go up.
This is completely experimental, but after reading through pathfinding I learned many new things I never knew. Try this, it’s an edited version of their sample script.
local PathfindingService = game:GetService("PathfindingService")
-- Variables for the zombie, its humanoid, and destination
local npc = ""-- remove quotes and put the npc here
local humanoid = npc.Humanoid
local destination = "" -- remove quotes and put the destination here
-- Create the path object
local path = PathfindingService:CreatePath()
-- Variables to store waypoints table and zombie's current waypoint
local waypoints
local currentWaypointIndex
local function followPath(destinationObject)
-- Compute and check the path
path:ComputeAsync(npc.HumanoidRootPart.Position, destinationObject.PrimaryPart.Position)
-- Empty waypoints table after each new path computation
waypoints = {}
if path.Status == Enum.PathStatus.Success then
-- Get the path waypoints and start zombie walking
waypoints = path:GetWaypoints()
-- Move to first waypoint
currentWaypointIndex = 1
humanoid:MoveTo(waypoints[currentWaypointIndex].Position)
else
-- Error (path not found); stop humanoid
humanoid:MoveTo(npc.HumanoidRootPart.Position)
end
end
local function onWaypointReached(reached)
if reached and currentWaypointIndex < #waypoints then
currentWaypointIndex = currentWaypointIndex + 1
humanoid:MoveTo(waypoints[currentWaypointIndex].Position)
end
end
local function onPathBlocked(blockedWaypointIndex)
-- Check if the obstacle is further down the path
if blockedWaypointIndex > currentWaypointIndex then
-- Call function to re-compute the path
followPath(destination)
end
end
-- Connect 'Blocked' event to the 'onPathBlocked' function
path.Blocked:Connect(onPathBlocked)
-- Connect 'MoveToFinished' event to the 'onWaypointReached' function
humanoid.MoveToFinished:Connect(onWaypointReached)
followPath(destination)
Be sure to add in the variables at the beginning. I am not sure if this will do anything, it’s just something to try before having to move around your whole build. Let me know how it goes!