How to make my pathfinding npc smarter?

my pathfinding npc is suppose to follow me with the help of pathfinding links, but for some reason it does all of this
https://gyazo.com/731577431457ed9f0d2836c5f7f9f600

and whenever I get near the NPC, it slightly tiptoes to me and stops

Error:
Workspace.Dummy.Script:37: attempt to index nil with ‘Position’

local pfs = game:GetService("PathfindingService")
local wps = {}
local path = pfs:CreatePath()
local wpIdx = 1
local char = script.Parent
local hum = char:WaitForChild("Humanoid")
local hrp = char:WaitForChild("HumanoidRootPart")

local humrp = char.HumanoidRootPart

local function findTarget()
	local players = game.Players:GetPlayers()
	local MaxDistance = 9999999999
	local nearestTarget

	for i,v in pairs(players) do
		if (v.Character) then
			local target = v.Character
			local distance = (humrp.Position - target.HumanoidRootPart.Position).Magnitude

			if (distance < MaxDistance) then
				nearestTarget = target
				MaxDistance = distance
			end
		end
	end

	return nearestTarget
end

local function followPath(goal)
	path:ComputeAsync(hrp.Position, goal.Position)
	wps = {}
	if path.Status == Enum.PathStatus.Success then
		wps = path:GetWaypoints()
		wpIdx = 1
		hum:MoveTo(wps[wpIdx].Position)
	end
end

hum.MoveToFinished:Connect(function(reached)
	if reached and wpIdx < #wps then
		wpIdx += 1
		if wps[wpIdx].Action == Enum.PathWaypointAction.Jump then
			hum.Jump = true
		end
		hum:MoveTo(wps[wpIdx].Position)
	end
end)

path.Blocked:Connect(function(blockedWpIDX)
	if blockedWpIDX > wpIdx then
		local target = findTarget(script.Parent.HumanoidRootPart)
		if target ~= nil then
			followPath(target.Torso, target)
		end
	end
end)

game:GetService("RunService").Heartbeat:Connect(function(deltatime)
	local target = findTarget(script.Parent.HumanoidRootPart)
	if target ~= nil then
		followPath(target.Torso, target)
	end
end)
3 Likes

You didn’t make any agent parameters. What is your pathfinding link for the ladder called?

2 Likes

the link is called “PathfindingLink”

2 Likes

Set AgentCanClimb to true in your agent parameters then and don’t change the cost since PathfindingLinks automatically have a cost of 1.

Code:

local pfs = game:GetService("PathfindingService")
local wps = {}
local path = pfs:CreatePath({
	AgentCanClimb = true,
})

local wpIdx = 1
local char = script.Parent
local hum = char:WaitForChild("Humanoid")
local hrp = char:WaitForChild("HumanoidRootPart")

local humrp = char.HumanoidRootPart

local function findTarget()
	local players = game.Players:GetPlayers()
	local MaxDistance = math.huge
	local nearestTarget = nil

	for i,v in players do
		if (v.Character) then
			local target = v.Character
			local distance = (humrp.Position - target.HumanoidRootPart.Position).Magnitude

			if (distance < MaxDistance) then
				nearestTarget = target
				MaxDistance = distance
			end
		end
	end

	return nearestTarget
end

local function followPath(goal)
	path:ComputeAsync(hrp.Position, goal.Position)
	table.clear(wps)
	
	if path.Status == Enum.PathStatus.Success then
		wps = path:GetWaypoints()
		wpIdx = 1
		hum:MoveTo(wps[wpIdx].Position)
	end
end

hum.MoveToFinished:Connect(function(reached)
	if reached and wpIdx < #wps then
		wpIdx += 1
		if wps[wpIdx].Action == Enum.PathWaypointAction.Jump then
			hum.Jump = true
		end
		hum:MoveTo(wps[wpIdx].Position)
	end
end)

path.Blocked:Connect(function(blockedWpIDX)
	if blockedWpIDX > wpIdx then
		local target = findTarget(script.Parent.HumanoidRootPart)
		if target then
			followPath(target.Torso, target)
		end
	end
end)

game:GetService("RunService").Heartbeat:Connect(function(deltatime)
	local target = findTarget(script.Parent.HumanoidRootPart)
	if target then
		followPath(target.Torso, target)
	end
end)
2 Likes

i’m still getting the same issue

1 Like

Did you set up your pathfinding link right?

2 Likes

Like this right?
asdasdasdasdasd
asdasdasdasdasdasd

1 Like

Yes, could you send another video?

2 Likes

https://gyazo.com/9d214948c162041a93091d26426fe5b4

1 Like

Fixed it!
I think it was because the function wasn’t waiting for it to be done moving.
I had to do task.wait, because hum.MoveToFinished:Wait() wouldn’t work for some reason.
It still twitches a little bit though.

local pfs = game:GetService("PathfindingService")
local wps = {}
local path = pfs:CreatePath({
	AgentCanClimb = true,
})
local wpIdx = 1
local char = script.Parent
local hum = char:WaitForChild("Humanoid")
local hrp = char:WaitForChild("HumanoidRootPart")

local humrp = char.HumanoidRootPart

local db = false

local function findTarget()
	local players = game.Players:GetPlayers()
	local MaxDistance = 9999999999
	local nearestTarget

	for i,v in pairs(players) do
		if (v.Character) then
			local target = v.Character
			local distance = (humrp.Position - target.HumanoidRootPart.Position).Magnitude

			if (distance < MaxDistance) then
				nearestTarget = target
				MaxDistance = distance
			end
		end
	end
	
	return nearestTarget
end

local function followPath(goal)
	db = true
	path:ComputeAsync(hrp.Position, goal.Position)
	wps = {}
	if path.Status == Enum.PathStatus.Success then
		wps = path:GetWaypoints()
		wpIdx = 1
		print(wps[wpIdx].Position)
		hum:MoveTo(wps[wpIdx].Position)
		task.wait(0.5)
		db = false
	end
end

hum.MoveToFinished:Connect(function(reached)
	if reached and wpIdx < #wps then
		wpIdx += 1
		if wps[wpIdx].Action == Enum.PathWaypointAction.Jump then
			hum.Jump = true
		end
		hum:MoveTo(wps[wpIdx].Position)
	end
end)

path.Blocked:Connect(function(blockedWpIDX)
	if blockedWpIDX > wpIdx then
		local target = findTarget(script.Parent.HumanoidRootPart)
		if target ~= nil then
			followPath(target.Torso, target)
		end
	end
end)

game:GetService("RunService").Heartbeat:Connect(function(deltatime)
	local target = findTarget(script.Parent.HumanoidRootPart)
	if target ~= nil and db == false then
		followPath(target.Torso, target)
	end
end)

EDIT:
The twitching and stuff might be able to be entirely gone if you found the path, made the dummy get to the end of the path, then make the path again, and repeat.

2 Likes

how do i make it find the path?

1 Like

Sorry if I worded it a bit weird, but you could just change your current code to make the debounce turn to false after looping through the waypoint table and moving to each, so then it would make another path.
I don’t really know how to explain it, sorry.

1 Like

can u show an example through code? i’m not really an expert scripter

1 Like

You could try something like this,

local pfs = game:GetService("PathfindingService")
local wps = {}
local path = pfs:CreatePath({
	AgentCanClimb = true,
})
local wpIdx = 1
local char = script.Parent
local hum = char:WaitForChild("Humanoid")
local hrp = char:WaitForChild("HumanoidRootPart")

local humrp = char.HumanoidRootPart

local db = false

local function findTarget()
	local players = game.Players:GetPlayers()
	local MaxDistance = 9999999999
	local nearestTarget

	for i,v in pairs(players) do
		if (v.Character) then
			local target = v.Character
			local distance = (humrp.Position - target.HumanoidRootPart.Position).Magnitude

			if (distance < MaxDistance) then
				nearestTarget = target
				MaxDistance = distance
			end
		end
	end

	return nearestTarget
end

local function followPath(goal)
	db = true
	path:ComputeAsync(hrp.Position, goal.Position)
	wps = {}
	if path.Status == Enum.PathStatus.Success then
		wps = path:GetWaypoints()
		for i,v in pairs(wps) do
			wpIdx += 1
			if i < #wps then
				if wps[i].Action == Enum.PathWaypointAction.Jump then
					hum.Jump = true
				end
				hum:MoveTo(wps[i].Position)
				hum.MoveToFinished:Wait()
			else
				db = false
			end
		end
	end
end

path.Blocked:Connect(function(blockedWpIDX)
	if blockedWpIDX > wpIdx then
		local target = findTarget(script.Parent.HumanoidRootPart)
		if target ~= nil then
			followPath(target.Torso, target)
		end
	end
end)

game:GetService("RunService").Heartbeat:Connect(function(deltatime)
	local target = findTarget(script.Parent.HumanoidRootPart)
	if target ~= nil and db == false then
		followPath(target.Torso, target)
	end
end)
2 Likes

the npc is definitely smarter and can get to me a lot easier, however now it’s stuttering like this:
https://gyazo.com/0ca7e4e95b1fba92fb079366a754c438

a thing like HumanoidRootPart:SetNetworkOwner( nil ) won’t work either

1 Like

I can’t really see any studdering?

2 Likes

I think he means that weird little dance/strut animation while walking but i could be wrong lol

2 Likes

yeah, it struggles to catch up with me too

1 Like

I think the little run animation is something your doing,
to fix the catching up issue,
check if the players CFrame has changed ever waypoint, if it changed, recalculate the path.

1 Like

I know i’m asking for a lot, but can u show an example through code? this is the last thing I need help with