Pathfinding gets stuck on certain height objects

Watch the video for it to make sense

As you can see the AI gets stuck on objects of certain height, in the script im aware that agent height is set to 0.01 however this is necessary as otherwise it will break and not be able to detect paths even when there is clearly a viable path available. So i need a way for it to not get stuck on those objects without the AgentHeight value being modified

script:

task.wait(5)

local shootModule  = require(game.ServerScriptService.NPCShoot)

local PathfindingService = game:GetService("PathfindingService")

local AI = script.Parent
local RP = script.Parent.HumanoidRootPart
local Hum = script.Parent.Humanoid

local Gun = script.Parent.Pistol


local Waypoints = game.Workspace:WaitForChild("Waypoints"):GetChildren()

RP:SetNetworkOwner(nil)

local attackAnim = Hum.Animator:LoadAnimation(script.Attack)
local walkAnim = Hum.Animator:LoadAnimation(script.Walk)
local runAnim = Hum.Animator:LoadAnimation(script.Run)

local rayParams = RaycastParams.new()
rayParams.FilterType = Enum.RaycastFilterType.Exclude
rayParams.FilterDescendantsInstances = {Hum}

local Damage = 25
local AttackRange = 15

local shootTrack = AI.Humanoid.Animator:LoadAnimation(game.ReplicatedStorage.Animations.NPCPistolShoot)

walkAnim.Looped = true
runAnim.Looped = true
walkAnim:Play()

local LastSeenPos

local RayParams = RaycastParams.new()
RayParams.FilterType = Enum.RaycastFilterType.Exclude

local pathParams = {
	AgentHeight = 0.01,
	AgentRadius = 0.01,
	AgentCanJump = true,
}

local function getPath(destination)

	if destination then
		print('Get path fired')

		local path = PathfindingService:CreatePath(pathParams)

		path:ComputeAsync(RP.Position - Vector3.new(0,RP.Size.Y/2,0), destination)

		return path	
	else
		warn("Pathfinding fail")
		return "Fail"
	end

end

function lineOfSight(target)
	local rayDirection = target.Position - RP.Position
	local rayParams = RaycastParams.new()
	rayParams.FilterDescendantsInstances = {RP.Parent}  

	local RayResult = workspace:Raycast(RP.Position, rayDirection, rayParams)

	-- Visualization
	local rayPart = Instance.new("Part")
	rayPart.Size = Vector3.new(0.2, 0.2, rayDirection.Magnitude)
	rayPart.CFrame = CFrame.new(RP.Position, target.Position) * CFrame.new(0, 0, -rayPart.Size.Z / 2)
	rayPart.Anchored = true
	rayPart.CanCollide = false
	rayPart.Color = Color3.new(1, 0, 0) -- Red color for the ray
	rayPart.Transparency = 0.5
	rayPart.Parent = RP.Parent
	rayPart.CanQuery = false
	rayPart.CanTouch = false
	-- Destroy the visualization after a short time
	game:GetService("Debris"):AddItem(rayPart, 0.2)

	if RayResult and RayResult.Instance then
		if RayResult.Instance:IsDescendantOf(target.Parent) then
			return true
		else
			return false
		end
	end
end


function getTarget()

	local closestTarget = nil
	local distanceFromClosestTarget = 1000000000

	for i, player in pairs(game.Players:GetChildren()) do
		local distance = (player.Character.HumanoidRootPart.Position - RP.Position).Magnitude

		if distance < distanceFromClosestTarget and player.Character.Humanoid.Health > 0 then
			distanceFromClosestTarget = distance
			closestTarget = player
		end
	end

	if closestTarget ~= nil then
		return(closestTarget)
	else
		task.wait(5)
		patrol()
	end


end

local db = false

local runAnimPlayingStatus = false
local walkAnimPlayingStatus = false

function chaseTarget(target)

	if target.Character.Humanoid.Health > 0 then
		if runAnimPlayingStatus == false then
			walkAnim:Stop()
			runAnim:Play()
			runAnimPlayingStatus = true
			walkAnimPlayingStatus = false
		end


		local path

		path = getPath(target.Character.HumanoidRootPart.Position)

		if path ~= "Fail" then
			local waypoints = path:GetWaypoints()

			if waypoints[2] then
				Hum:MoveTo(waypoints[2].Position)


				local humTarget = getTarget()
				local LineOfSight = lineOfSight(humTarget.Character.HumanoidRootPart)

				LastSeenPos = humTarget.Character.HumanoidRootPart.Position

				if (humTarget.Character.HumanoidRootPart.Position - RP.Position).Magnitude <= 20 and db == false then

					if AI.Humanoid.Health > 0 and Gun:GetAttribute("Reloading") == false and humTarget.Character.Humanoid.Health > 0 then

						runAnim:Stop()
						shootTrack:Play()
						db = true
						shootModule.Shoot(target, Gun, AI)
						runAnim:Play()
						task.delay(1, function()
							db = false
						end)
						patrol()
					else
						--patrol()
					end
				end

				if humTarget and LineOfSight then
					chaseTarget(humTarget)
				else
					if humTarget.Character.Humanoid.Health >  0 then
						moveToLastSeen(LastSeenPos)
					else
						patrol()
					end

				end
			else
				local ChosenWapoint = math.random(1, #Waypoints)
				moveTo(game.Workspace.Waypoints:FindFirstChild(ChosenWapoint).Position)
				warn("Path Failed to compute falling back")
				moveTo()
			end
		else

		end
	else
		task.wait(1)
		patrol()
	end



end


function moveToLastSeen(location)
	local path = getPath(location)

	if path ~= "Fail" then
		for i, waypoint in pairs(path:GetWaypoints()) do

			local humTarget = getTarget()
			local LineOfSight = lineOfSight(humTarget.Character.HumanoidRootPart)

			if humTarget and LineOfSight then
				path:Destroy()
				chaseTarget(humTarget)
				break
			else
				if walkAnimPlayingStatus == false then
					walkAnim:Play()
					walkAnimPlayingStatus = true
				end
				runAnimPlayingStatus = false
				runAnim:Stop()

				Hum:MoveTo(waypoint.Position)
				Hum.MoveToFinished:Wait()


				if i == #path:GetWaypoints() then
					patrol()
				end
			end
		end
	else

	end

end

function moveTo(target)

	local humTarget = getTarget()

	if humTarget ~= nil then
		local LineOfSight = lineOfSight(humTarget.Character.HumanoidRootPart)

		if humTarget and LineOfSight then
			chaseTarget(humTarget)
		else

			local path = getPath(target)

			if path.Status == Enum.PathStatus.Success then


				for i, waypoint in pairs(path:GetWaypoints()) do

					local humTarget = getTarget()
					local LineOfSight = lineOfSight(humTarget.Character.HumanoidRootPart)

					if humTarget and LineOfSight then
						path:Destroy()
						chaseTarget(humTarget)
						break
					else
						if walkAnimPlayingStatus == false then
							walkAnim:Play()
							walkAnimPlayingStatus = true
						end


						runAnimPlayingStatus = false
						runAnim:Stop()

						Hum:MoveTo(waypoint.Position)
						Hum.MoveToFinished:Wait()


						if i == #path:GetWaypoints() then
							patrol()
						end
					end
				end
			end	
		end
	else
		print("Hum target is nil")
	end
end


function patrol()
	local ChosenWapoint = math.random(1, #Waypoints)
	moveTo(game.Workspace.Waypoints:FindFirstChild(ChosenWapoint).Position)
end

script.Parent.Humanoid.Died:Connect(function()
	script:Destroy()
	Hum.HealthDisplayDistance = 0
end)

local lastPos = RP.Position

function stuckDetect()
	while task.wait(1) do
		if (RP.Position - lastPos).Magnitude < 1 and Gun:GetAttribute("Reloading") == false then
			warn("AI got stuck falling back")
			--patrol()
		else
			lastPos = RP.Position
		end
	end
end

task.spawn(stuckDetect)

patrol()
1 Like

I fixed it by adding a part above that table that they got stuck on thats bigger then the table and set the collision group of it such that the AI can collide with it but the player cant, now the AI goes around the big part and it works fine