Ideas on how to make a better Pathfinding NPC

So if you know pathfinding service, you would know it looks something like this:

local PFS = game:GetService("PathfindingService")

local root = script.Parent:WaitForChild("HumanoidRootPart")
local humanoid = script.Parent:WaitForChild("Humanoid")
local destination = game.Workspace:FindFirstChild("Part")

local path = PFS:CreatePath()
path:ComputeAsync(root.Position,destination.Position)

local waypoints
waypoints = path:GetWaypoints()

for i,v in pairs(waypoints) do
	humanoid:MoveTo(v.Position)
	
	if v.Action == Enum.PathWaypointAction.Jump then
		humanoid.Jump = true
	end
	
	humanoid.MoveToFinished:Wait()
end

The problem is, let’s say while the NPC is walking to the path, the waypoint is blocked by a part. The NPC wouldn’t be smart enough to just dodge the part. I heard that you can use a path.Blocked event to solve this, but I had no idea how, any good ideas to achieve this?

EDIT 1:
A quick question, how can I set the AgentParams to CreatePath()? I can’t seem to work it out.

3 Likes

if you want to create a good pathfinding A* use raycasting its always easier and works for me you can find the closest ray for A* and when a ray gives signal that it sees end, you gotta make A* follow this ray

Instead of using humanoid.MoveToFinished:Wait(), you might have to use something a little more ugly

--local studsPerWait = humanoid.WalkSpeed/3 -- mess around with this, it'd be related to WalkSpeed
local expectedWaitAmount =100-- (root.Position-v.Position).Magnitude * studsPerWait
local i=0
repeat wait() i+=1
until ((root.Position-v.Position).Magnitude <= 2) or i>=expectedWaitAmount*1.3 -- give it some cushion

if not ((root.Position-v.Position).Magnitude <= 2) then
-- you have to recalculate the route
end

this is untested code
There might be a better solution than this performance wise, but this is something you could try out off the top of my head

Another solution would be to disable collisions for NPCs
Here’s one way you could do it:

The Developer Hub actually gives you an example, and explains how to use the Blocked event in PathFinding: PathFinding Article

That doesn’t help, I’m using an easier script like the one in this post.

Seems like it could help, but you have any idea in the script?

So you want an easier way to detect if the NPC hits something? I’m not sure honestly if there’s an easier way. The Blocked event was specifically designed to handle NPCs and other objects with humanoids running into things.

Your original question of not knowing how to use the blocked event made it sound like you wanted to learn how to use it.

What’s I’m trying to ask is, is there any alternative way using path.Blocked event instead of just using Roblox’s? Because I’m pretty sure lot of developers used the method in this post. I’m just curious on how to use this event to handle incoming blocked paths.

Well, I found myself a solution. I just need to put this in a RunService loop and make function that creates and computes async the path so that it will keep creating new possible paths. Thank you for everyone’s help!

2 Likes

Great solution, however I also believe that you could create a function that creates a new path, then whenever a path is blocked at some point (you can use the Blocked Event to handle this), just call that function that made the path. I don’t know if this actually works because I haven’t tested it, but that’s my logic. Maybe my logic wrong though.

1 Like

Our game uses pathfinding for our mobs - a great tip would be not to re-compute it every loop, but only whenever it meets some criteria.

The criteria could be:
A) Player / Target is more than X studs away from all nodes (check in reverse order for optimizations :-) )
B) Path is blocked / unable to calculate
C) NPC has finished traversing the path

2 Likes

That logo is what I used, which is remaking the path = re-ComputeAsycn() it.

This is the only criteria I didn’t used.