Help with pathfinding

Hello, I’m trying to make a monster however there are a few issues.

  1. The monster runs into walls often even though a pathModifier has been set so the monster can go through doors
  2. The monster movement is very figity and the monster will sometimes walk in the wrong direction for a few seconds before correcting its movement

As you can see here, I have this “house” with a path modifier showing the door:

The monster is always given the position of the player and should walk through the door but instead does this:
image

Example of monster movement:

Here is my code:

local Rig = script.Parent
local Humanoid = Rig:WaitForChild("Humanoid")
local Root = Rig.HumanoidRootPart
local Idle = Humanoid.Idle
local Crawl = Humanoid.Crawl
local Animator = Humanoid:WaitForChild("Animator")
local IdleAnimation = Animator:LoadAnimation(Idle)
local CrawlAnimation = Animator:LoadAnimation(Crawl)
local PathfindingService = game:GetService("PathfindingService")


local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection

function goToLocation(location)
	
	local path = PathfindingService:CreatePath()
	local success,failure = pcall(function()
		path:ComputeAsync(location, Root.Position)
	end)
	
	if success and path.Status == Enum.PathStatus.Success then
		waypoints = path:GetWaypoints()
		
		blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
			if blockedWaypointIndex >= nextWaypointIndex then
				blockedConnection:Disconnect()
				goToLocation(location)
			end
		end)
		
		if not reachedConnection then
			reachedConnection = Humanoid.MoveToFinished:Connect(function(reached)
				if reached and nextWaypointIndex < #waypoints then
					nextWaypointIndex += 1
					Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
				else
					reachedConnection:Disconnect()
					blockedConnection:Disconnect()
					print('k')
					CrawlAnimation.Looped = false
					CrawlAnimation:Stop()
				end
			end)
		end
		
		nextWaypointIndex = 2
		CrawlAnimation.Looped = true
		CrawlAnimation:Play()
		Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
	else
		warn("Path not computed!", failure)
	end
end

task.wait(3)
print("starting")
while true do
	goToLocation(game.Players.KrimsonWoIf.Character.HumanoidRootPart.Position)
	print("w")
	task.wait(1)
end

Here is how the monster is made:
image

you will need to add this to your code

local path = PathfindingService:CreatePath({
	AgentRadius = 3,
	AgentHeight = 6,
	AgentCanJump = false,
Costs = {
		LabelText = math.huge()
	}
}

Inside the Costs table you need to add the Label attribute of the PathfindingModifier with it equaling math.huge() EG:

Costs = {
		LabelText = math.huge()
	}

image

This will stop the monster running into anything with this pathfinding modifier

Okay I tried doing

	local path = PathfindingService:CreatePath({
		AgentRadius = 3,
		AgentHeight = 6,
		AgentCanJump = false,
		Costs = {
			ThisText = 100
		}
	})
	```

and this was the result

Instead of having a While true loop, instead when the path ends then call the function again, because you are making too many paths the movement will jitter as its calculating the next path

Also create the path variable at the start of the script as shown below:

local Rig = script.Parent
local Humanoid = Rig:WaitForChild("Humanoid")
local Root = Rig.HumanoidRootPart
local Idle = Humanoid.Idle
local Crawl = Humanoid.Crawl
local Animator = Humanoid:WaitForChild("Animator")
local IdleAnimation = Animator:LoadAnimation(Idle)
local CrawlAnimation = Animator:LoadAnimation(Crawl)
local PathfindingService = game:GetService("PathfindingService")


local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local path = PathfindingService:CreatePath({
		AgentRadius = 3,
		AgentHeight = 6,
		AgentCanJump = false,
		Costs = {
			ThisText = 100
		}
	})

Then just call the ComputeAsync function on the path variable

Okay I put the path outside

local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection

local path = PathfindingService:CreatePath({
AgentRadius = 3,
AgentHeight = 6,
AgentCanJump = false,
Costs = {
ThisText = 100
}
})

function goToLocation(location)

and I got rid of the while loop and repeated the function when it ended:

if reached and nextWaypointIndex < #waypoints then
					nextWaypointIndex += 1
					Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
				else
					reachedConnection:Disconnect()
					blockedConnection:Disconnect()
					CrawlAnimation.Looped = false
					CrawlAnimation:Stop()
					goToLocation(game.Players.KrimsonWoIf.Character.HumanoidRootPart.Position)
				end

here is the result:

I believe its because the NPC had 2 paths running at the same time, so it walked to a waypoint on one path, but then went to another waypoint from another path.

If this is the case, this sanity check might help

Add a variable at the start of the script called
TickTime

Add a local variable inside the goToLocation() function called
CurrentTime

Update both variables to the os.time() when goToLocation() called

Then before you call the function:
Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
create an if statement to check whether CurrentTime and TickTime are the same.
If they are then use the MoveTo function, and if not then dont do anything

what if instead of doing all that I just did a debounce?

local debounce = false
local function printHello()
if debounce == false then
debounce = true
print("Hello")
task.wait(0.5)
debounce = false
else 
print("already going")
end
end


printHello() -- "Hello"
printHello() -- "already going"

that could work yeah

**3*0cars

its still doing this

Here are my thoughts…

  1. Why does it go back to its starting location?
  2. Why does it stop moving when its not in a while loop?

here is the full script:

local Rig = script.Parent
local Humanoid = Rig:WaitForChild("Humanoid")
local Root = Rig.HumanoidRootPart
local Idle = Humanoid.Idle
local Crawl = Humanoid.Crawl
local Animator = Humanoid:WaitForChild("Animator")
local IdleAnimation = Animator:LoadAnimation(Idle)
local CrawlAnimation = Animator:LoadAnimation(Crawl)
local PathfindingService = game:GetService("PathfindingService")


local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local debounce = false

local path = PathfindingService:CreatePath({
	AgentRadius = 3,
	AgentHeight = 6,
	AgentCanJump = false,
	Costs = {
		ThisText = 100
	}
})


function goToLocation(location)
	if debounce == false then
		debounce = true
		local success,failure = pcall(function()
			path:ComputeAsync(location, Root.Position)
		end)

		if success and path.Status == Enum.PathStatus.Success then
			waypoints = path:GetWaypoints()

			blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
				if blockedWaypointIndex >= nextWaypointIndex then
					blockedConnection:Disconnect()
					goToLocation(location)
				end
			end)

			if not reachedConnection then
				reachedConnection = Humanoid.MoveToFinished:Connect(function(reached)
					if reached and nextWaypointIndex < #waypoints then
						nextWaypointIndex += 1
						Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
					else
						reachedConnection:Disconnect()
						blockedConnection:Disconnect()
						CrawlAnimation.Looped = false
						CrawlAnimation:Stop()
						debounce = false
						goToLocation(game.Players.KrimsonWoIf.Character.HumanoidRootPart.Position)
					end
				end)
			end

			nextWaypointIndex = 2
			CrawlAnimation.Looped = true
			CrawlAnimation:Play()
			Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
		else
			warn("Path not computed!", failure)
		end
	end
end

task.wait(3)
print("starting")

goToLocation(game.Players.KrimsonWoIf.Character.HumanoidRootPart.Position)



try to remove the if not reachedConnection then and just create the new connection whenever a path is calculated

also forgot debounce = false in the path.Blocked function

this worked however for some reason it keeps walking back to its starting point

here is the current script:

local Rig = script.Parent
local Humanoid = Rig:WaitForChild("Humanoid")
local Root = Rig.HumanoidRootPart
local Idle = Humanoid.Idle
local Crawl = Humanoid.Crawl
local Animator = Humanoid:WaitForChild("Animator")
local IdleAnimation = Animator:LoadAnimation(Idle)
local CrawlAnimation = Animator:LoadAnimation(Crawl)
local PathfindingService = game:GetService("PathfindingService")


local waypoints
local nextWaypointIndex
local reachedConnection
local blockedConnection
local debounce = false

local path = PathfindingService:CreatePath({
	AgentRadius = 3,
	AgentHeight = 6,
	AgentCanJump = false,
	Costs = {
		ThisText = 100
	}
})


function goToLocation(location)
	if debounce == false then
		debounce = true
		local success,failure = pcall(function()
			path:ComputeAsync(location, Root.Position)
		end)

		if success and path.Status == Enum.PathStatus.Success then
			waypoints = path:GetWaypoints()

			blockedConnection = path.Blocked:Connect(function(blockedWaypointIndex)
				if blockedWaypointIndex >= nextWaypointIndex then
					blockedConnection:Disconnect()
					debounce = false
					goToLocation(game.Players.KrimsonWoIf.Character.HumanoidRootPart.Position)
				end
			end)


				reachedConnection = Humanoid.MoveToFinished:Connect(function(reached)
					if reached and nextWaypointIndex < #waypoints then
						nextWaypointIndex += 1
						Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
					else
						reachedConnection:Disconnect()
						blockedConnection:Disconnect()
						CrawlAnimation.Looped = false
						CrawlAnimation:Stop()
						debounce = false
						goToLocation(game.Players.KrimsonWoIf.Character.HumanoidRootPart.Position)
					end
				end)
			

			nextWaypointIndex = 2
			CrawlAnimation.Looped = true
			CrawlAnimation:Play()
			Humanoid:MoveTo(waypoints[nextWaypointIndex].Position)
		else
			warn("Path not computed!", failure)
		end
	end
end

task.wait(6)
print("starting")

goToLocation(game.Players.KrimsonWoIf.Character.HumanoidRootPart.Position)



you have put the arguments of the ComputeAsync the wrong way around