Pathfinding Service not calculating a proper path

Currently, I am trying to make a PathFinding AI which sticks to a path, because it is frustrating when it finds the quickest route, not the most practical way. For example, the NPC jumping over railing instead of walking three more studs to walk up the said stairs.

After watching and mimicking a video that provided code for a raycasting and magnitude pathfinding (using the pathfinding service, because all of the open source A* pathfinding scripts are out of date), I made the following script that needs two parameters: The NPC’s name and the Goal point.

Then, I planned to use Collision groups to make invisible borders around the paths, so that the NPC stayed within the boundries.

WorkSpace = game:GetService("Workspace")
local func = {}
	func.WalkTo = function(who,objective)
		WorkSpace:WaitForChild(who):WaitForChild("HumanoidRootPart"):SetNetworkOwner(nil)
		repeat wait()
		local rootPart = WorkSpace:WaitForChild(who):WaitForChild("HumanoidRootPart")
		local human = WorkSpace:WaitForChild(who):WaitForChild("Humanoid")
		local function findTarget()
			local dist = 200
			local target = WorkSpace:WaitForChild("Nodes"):WaitForChild(objective)
			return target
		end
		
		local goal = findTarget()
		if goal then
			local ray = Ray.new(rootPart.Position, (goal.Position - rootPart.Position).Unit * 200)
			local hit,position = WorkSpace:FindPartOnRayWithIgnoreList(ray,{WorkSpace:WaitForChild(who)})
			if hit then
				if hit:IsDescendantOf(goal.Parent) then
					human:MoveTo(goal.Position)
				else
					human:MoveTo(goal.Position)
					wait()
					
					local pathfindingService = game:GetService("PathfindingService")
					local pathParams = {
						AgentHeight = 5,
						AgentRadius = 2,
						AgentCanJump = false
					}
					local path = pathfindingService:CreatePath(pathParams)
					local newpath = path:ComputeAsync(rootPart.Position,goal.Position)
					local points = path:GetWaypoints()
					
					if path.Status == Enum.PathStatus.Success then
						for i,v in pairs (points) do
							human:MoveTo(v.Position)
							human.MoveToFinished:Wait()
							if v.Action == Enum.PathWaypointAction.Jump then
								human.Jump = true
							end
							if (points[#points].Position - goal.Position).magnitude > 15 then
								break
							end
						end
					else
						warn("No Path Found")
						break
						--human:MoveTo(goal.Position)
					end
				end
			end
		end
		until (WorkSpace:WaitForChild(who):WaitForChild("HumanoidRootPart").Position - WorkSpace:WaitForChild("Nodes"):WaitForChild(objective).Position).magnitude < 3
end

return func

But the problem is that it does not take heed of the invisible barriers, and instead tries to go straight towards the goal point:

But in the GIF below, you can see that it IS generating a path in a wider enviroment:

I’ve tried disabling the collision group script, tweaking values, etc. I’d hate to see that it’s impossible for Pathfinding Service to generate a path in a tight environment. If anyone could point me in the right direction it would be fantastic!

Place with scripts: PathfindingNew.rbxl (23.4 KB)

If all you are wanting to do is prevent the humanoid from jumping to make a faster path, you could try the new pathfinding agent parameters. You can adjust the AgentRadius and the bool AgentCanJump to ensure it will focus on how practical the route is instead of how quick it is.

1 Like

Sorry that this might come off as stupid, but how would I implement those new perimeters into PathfindingService?

1 Like

PathfindingService:CreatePath({AgentRadius = 2, AgentHeight = 5})

You can change the Radius and Height.

There are two if statements testing the same thing inside of each other. The nested function would be best moved out.

The find target function is simply setting the target to the goal point every time. You mentioned raycasting. I see a ray that is never used and isn’t cast anywhere. What is the name of the algorithm? If it doesn’t precompute and prepare a map for fast pathfinding queries, then it is going to run very slowly.

There are a couple implementations posted or linked to on this forum, I’d do a quick search or pull up a tutorial or a paper describing A*. You could try to fight the Roblox Pathfinder, but you’ll get so much more from writing your own.

Btw, editing the heuristic to include additional costs is a very common requirement for games. In some games, NPCs don’t want to drown in the raging river instead of walking over the sturdy stone bridge. Crazy, right? Some want to stay close to their own terms territory. Some want to stay out of sight. Yet others have an objective to stay near while protecting it. The zombies would really prefer not to walk on the Lava bricks.

Other features are easy to add too like only flying vehicles can use flying nodes. Only friendly units can use friendly doors. Some doors can be opened when you get to them, crazy huh? Elevators can be used if the enemies are in the stairway. None of it is possible with the Roblox Pathfinder.

2 Likes

Thanks for pointing out that it wasn’t casting the ray anywhere, weird… I must have accidentally deleted that part somewhere along the line. Anyways, I fixed my post with the new code :slightly_smiling_face: