Pathfinding gets confused

When the npc gets blocked by a part, it would go to a random destination but the pathfinding gets confused.

local RunService = game:GetService("RunService")
local PathfindingService = game:GetService("PathfindingService")

local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")

local waypointsFolder = workspace:WaitForChild("Waypoints") -- The Red Blocks in the Video

local function randomWaypoint()
	local waypoint = waypointsFolder:GetChildren()
	local random = waypoint[math.random(1, #waypoint)]
	return random
end

local function WalkTo(waypoint)
	local pathParams = {
		AgentHeight = character:GetExtentsSize().Y,
		AgentRadius = character:GetExtentsSize().X,
		AgentCanJump = false,
		Costs = {
			Danger = math.huge,
		}
	}
	
	local path = PathfindingService:CreatePath(pathParams)
	
	local success, errorMessage = pcall(function()
		path:ComputeAsync(character.PrimaryPart.Position, waypoint.Position)
	end)
	
	if success and path.Status == Enum.PathStatus.Success then
		path.Blocked:Connect(function(blockedWaypointIndex)
			WalkTo(randomWaypoint())
		end)
		
		for i,v in pairs(path:GetWaypoints()) do
			repeat
				humanoid:MoveTo(v.Position)
			until humanoid.MoveToFinished:Wait()
		end
		
		task.wait(math.random(0,3))
		WalkTo(randomWaypoint())
	end
end

WalkTo(randomWaypoint())

2 Likes

You should try utilizing the errorMessage and the PathStatus, as both can tell you if something is blocking it or causing to glitch out. You can do this by trying to reset the path if an error has occurred using the PathStatus and errorMessage.

All it prints is nil.

print(errorMessage)

Doesn’t seem to work. Am I doing something wrong?

local RunService = game:GetService("RunService")
local PathfindingService = game:GetService("PathfindingService")

local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")

local DestinationsFolder = workspace:WaitForChild("Destinations")

local function randomWaypoint()
	local waypoint = DestinationsFolder:GetChildren()
	local random = waypoint[math.random(1, #waypoint)]
	return random
end

local function WalkTo(waypoint)
	local pathParams = {
		AgentHeight = character:GetExtentsSize().Y,
		AgentRadius = character:GetExtentsSize().X,
		AgentCanJump = false,
		Costs = {
			Danger = math.huge,
		}
	}
	
	local path = PathfindingService:CreatePath(pathParams)
	
	local success, errorMessage = pcall(function()
		path:ComputeAsync(character.PrimaryPart.Position, waypoint.Position)
	end)
	
	if success and path.Status == Enum.PathStatus.Success then
		path.Blocked:Connect(function(blockedWaypointIndex)
			WalkTo(randomWaypoint())
		end)
		
		for i,v in pairs(path:GetWaypoints()) do
			repeat
				humanoid:MoveTo(v.Position)
			until humanoid.MoveToFinished:Wait()
		end
		
		task.wait(math.random(0,3))
		WalkTo(randomWaypoint())
	else
		WalkTo(randomWaypoint())
	end
end

WalkTo(randomWaypoint())

Do you want it to jump over it or walk around?

I only want it to walk, no jumping.

Is the character always supposed to be walking?

The npc will stop at a random destination and continues walking after a few seconds.

You’re not moving to a random destination, you’re moving to a random waypoint on the path, which you are only calculating at the start.You’ve created a loop, that keeps walking to randomWaypoint, but randomwaypoint will always be a point on the path, so it’ll just

  1. walk to point
  2. get blocked, walk to random point on current path
  3. repeat

So how can I fix the confusion when the path gets blocked?

I don’t know, because I don’t know what you’re trying to do. if you’re trying to get it to just go to the waypoint, maybe make it recalculate the path when it gets blocked instead of going to a random waypoint on the path.

Im trying to make a system like GTA where npcs walk around.

Well, in that case, you should just have it recalculate the path. Waypoints will be the possible locations it can go to. Don’t have it do WalkTo every loop, only have it do WalkTo when 1. it gets blocked or 2. it’s arrived

Ok, seems fixed but how can I detect if there are no possible ways to get to the destination?

uhhm there might be a problem in my script

local function WalkTo(waypoint)
	local pathParams = {
		AgentHeight = character:GetExtentsSize().Y,
		AgentRadius = character:GetExtentsSize().X,
		AgentCanJump = false,
		Costs = {
			Danger = math.huge,
		}
	}
	
	local path = PathfindingService:CreatePath(pathParams)
	
	local success, errorMessage = pcall(function()
		path:ComputeAsync(character.PrimaryPart.Position, waypoint.Position)
	end)
	
	if success and path.Status == Enum.PathStatus.Success then
		path.Blocked:Connect(function(blockedWaypointIndex)
			WalkTo(waypoint)
		end)
		
		for i,v in pairs(path:GetWaypoints()) do
			repeat
				humanoid:MoveTo(v.Position)
			until humanoid.MoveToFinished:Wait()
		end
		
		task.wait(math.random(0,3))
		WalkTo(randomWaypoint())
	else
		WalkTo(randomWaypoint())
	end
end

Here ya go.
https://i.gyazo.com/37849e94301de2e415facd54e522407d.mp4


local RunService = game:GetService("RunService")
local PathfindingService = game:GetService("PathfindingService")

local character = script.Parent
local humanoid = character:WaitForChild("Humanoid")

local waypointsFolder = workspace:WaitForChild("Waypoints") -- The Red Blocks in the Video

wait(1)
local function randomWaypoint()
	local waypoint = waypointsFolder:GetChildren()
	local random = waypoint[math.random(1, #waypoint)]
	return random
end

local pathParams = {
	AgentHeight = character:GetExtentsSize().Y,
	AgentRadius = character:GetExtentsSize().X,
	AgentCanJump = false,
	Costs = {
		Danger = math.huge,
	}
}

local path = PathfindingService:CreatePath(pathParams)


local function WalkTo(waypoint)
	local Blocked = false


	local success, errorMessage = pcall(function()
		path:ComputeAsync(character.PrimaryPart.Position, waypoint.Position)
	end)


	if success and path.Status == Enum.PathStatus.Success then
		path.Blocked:Connect(function(blockedWaypointIndex)
			
			print("Blocked.")
			Blocked = true
			path:ComputeAsync(character.PrimaryPart.Position, randomWaypoint().Position)
		end)
		

		for i,v in pairs(path:GetWaypoints()) do
			repeat
				humanoid:MoveTo(v.Position)
			until humanoid.MoveToFinished:Wait() or Blocked
			if Blocked then
				break
			end
		--	path:ComputeAsync(character.PrimaryPart.Position, randomWaypoint().Position)
			
			
		end
		WalkTo(randomWaypoint())
		
		
	end
	
end

WalkTo(randomWaypoint())

Ohh, I forgot to disconnect it after it gets blocked. My bad.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.