My pathfinding npc gets stuck some corners and fails some jumps

I made a npc that follows the nearest player by using pathfinding and it works well but sometimes it gets stuck some corners (sometimes it could get rid of these stucks but sometimes it coudlnt) and fails some jumps while it is really easy to jump and pass. so basically i guess i need to make my npc smarter and recompute the path when it gets stuck? here’s the code and a video

local pfs = game:GetService("PathfindingService")
local npc = script.Parent
local humanoid = npc.Humanoid
local root = npc.HumanoidRootPart
local head = npc.Head

local pathparams = {
	AgentRadius = 2,
	AgentHeight = 5,
	AgentCanJump = true,
	AgentCanClimb = true,
}

function walkrandom()
	local xrandom = math.random(-10,10)
	local zrandom = math.random(-10,10)
	local goal = root.Position + Vector3.new(xrandom, 0, zrandom)
	
	local path = pfs:CreatePath(pathparams)
	path:ComputeAsync(root.Position - Vector3.new(root.Size.Y/0.75, 0), goal)
	
	if path.Status == Enum.PathStatus.Success then
		local waypoints = path:GetWaypoints()

		for _, waypoint in ipairs(waypoints) do
			if waypoint.Action == Enum.PathWaypointAction.Jump then
				humanoid.Jump = true
			end
			humanoid:MoveTo(waypoint.Position)
			local timeout = humanoid.MoveToFinished:Wait()

			if not timeout then

				print("got stuck")
				humanoid.Jump = true
				walkrandom()
			end
		end
	else
		print("path failed")
		wait(0.6)
		walkrandom()
	end
end

function pathfind(target)
	local path = pfs:CreatePath(pathparams)
	path:ComputeAsync(root.Position, target.Position)
	
	if path.Status == Enum.PathStatus.Success then
		
		local waypoints = path:GetWaypoints()
		
		--[[for _, waypoint in ipairs(waypoints) do
			local pointpart = Instance.new("Part", workspace)
			pointpart.Shape = Enum.PartType.Ball
			pointpart.Size = Vector3.new(1,1,1)
			pointpart.Material = Enum.Material.Neon
			pointpart.Color = Color3.fromRGB(255, 255, 255)
			pointpart.Anchored = true
			pointpart.CanCollide = false
			pointpart.Position = waypoint.Position
			pointpart.Name = "pointpart"
			
			pointpart.Touched:Connect(function(hitpart)
				if hitpart:IsDescendantOf(root.Parent) then
					pointpart:Destroy()
				end
			end)
		end]]
		
		for _, waypoint in ipairs(waypoints) do
			
			
			if waypoint.Action == Enum.PathWaypointAction.Jump then
				humanoid.Jump = true
			end
			humanoid:MoveTo(waypoint.Position)
			local timeout = humanoid.MoveToFinished:Wait()

			if not timeout then

				print("got stuck")
				humanoid.Jump = true
				walkrandom()
				break
			end
			if checksight(target) then
				repeat --sadsadsadsadkhjghcfghgvjbklıhugf
					print("moving to the target")
					humanoid:MoveTo(target.Position)
					wait(0.01)
					if target == nil then
						break
					elseif
						target.Parent == nil then
						break
					end
				until checksight(target) == false or humanoid.Health < 1 or target.Parent.Humanoid.Health < 1
				break
			end
			if (root.Position - waypoints[1].Position).Magnitude > 20 then
				print("target has moved, generating new path")
				pathfind(target)
				break
			end
		end
	end
end


function checksight(target)
	
	local rcparams = RaycastParams.new()
	rcparams.IgnoreWater = false
	rcparams.FilterDescendantsInstances = {script.Parent}
	local filtertype = Enum.RaycastFilterType.Exclude
	
	local ray = game.Workspace:Raycast(root.Position, (target.Position - root.Position).Unit * 40, rcparams)
	
	if ray then
		
		local hitpart = ray.Instance
		
		if hitpart then
			if hitpart:IsDescendantOf(target.Parent) and math.abs(hitpart.Position.Y - root.Position.Y) < 3 then
				print("can see the target")
				return true
			end
		end
	end
	return false
end

function findtarget()
	local distance = 150
	local target = nil
	local potential_targets = {}
	local seetargets = {}
	
	for i, v in ipairs(workspace:GetChildren()) do
		local humanoidtarget = v:FindFirstChild("Humanoid")
		local torsotarget = v:FindFirstChild("Torso") or v:FindFirstChild("HumanoidRootPart")
		if humanoidtarget and torsotarget and v.Name ~= script.Parent.Name then
			if (root.Position - torsotarget.Position).Magnitude < distance and humanoidtarget.Health > 0 then
				table.insert(potential_targets, torsotarget)
			end
		end
	end
	if #potential_targets > 0  then
		for i, v in ipairs(potential_targets) do
			
			if checksight(v) then
				table.insert(seetargets, v)
			elseif #seetargets == 0 and (root.Position - v.Position).Magnitude < distance then
				target = v
				distance = (root.Position - v.Position).Magnitude 
			end
		end
	end
	if #seetargets > 0 then
		distance = 150
		for i, v in ipairs(seetargets) do
			if (root.Position - v.Position).Magnitude < distance then
				target = v
				distance = (root.Position - v.Position).Magnitude 
			end
		end
	end
	return target
end

function main()
	local targettt = findtarget()	
	if targettt then
		humanoid.WalkSpeed = 16
		pathfind(targettt)
	else
		humanoid.WalkSpeed = 10
		walkrandom()
	end
end

while wait(0.01) do
	if humanoid.Health < 1 then
		break
	end
	main()
end

Sorry for video quality, it was so long i had to compress

1 Like
  1. you can mess with agentparams
  2. it fails because it doesnt check if theres a gap, your directly 'MoveTo’ing it forward after the NPC is in sight

so what i should do now? i really couldnt figure it out