Roblox ai Pathfinding goes over parts it is banned from doing so

Watch the video:

Here is the code:

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:FindFirstChildOfClass("Tool")

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 patrolPath

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

local pathParams = {
	AgentHeight = 1,
	AgentRadius = 1,
	AgentCanJump = false,
	Costs = {}

}

for i, v in pairs(game.Workspace:WaitForChild("AvoidPathing"):GetChildren()) do
	pathParams.Costs[v] = math.huge
end

local function getPath(destination)
	
	if typeof(destination) ~= "Vector3" then 
		warn("Destination variable was not a vector3")
	end
	
	
	if destination then
		local path = PathfindingService:CreatePath(pathParams)
		
		path:ComputeAsync(RP.Position , 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
			--	print("line of sight true")
			script.Parent["Body Colors"].HeadColor3 = Color3.new(0.192157, 1, 0.0666667)
			return true
		else
			--	print("line of sight false")
			script.Parent["Body Colors"].HeadColor3 = Color3.new(1, 0, 0.0156863)
			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
			if lineOfSight(player.Character.HumanoidRootPart) then
				if player.Character.Humanoid.Health > 0 then
					distanceFromClosestTarget = distance
					closestTarget = player
				end
			end
		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)
	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)
			task.spawn(shoot)
			
			if lineOfSight(target.Character.HumanoidRootPart) then
				patrol()
			else
				moveToLastSeen(target.Character.HumanoidRootPart.Position)
			end
			
			
		else
			patrol()
			return
		end

		
	end
	
end

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

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

			local humTarget = getTarget()

			if humTarget then
				patrol()
				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()
					break
				end
			end
		end
	else
		patrol()
	end

end


function moveTo(target)
	local humTarget = getTarget()
	
	if humTarget then
		if patrolPath then 
			patrolPath:Destroy()
		end
		chaseTarget(humTarget)
		return
	else
	
		patrolPath = getPath(target)
		
		if patrolPath.Status == Enum.PathStatus.Success then
			local Waypoints = patrolPath:GetWaypoints()
			for i, waypoint in pairs(Waypoints) do
				
				if i == #patrolPath:GetWaypoints() then
					patrol()
					break
				end
				
				 local humTarget = getTarget()

				if humTarget then
					chaseTarget(humTarget)
					break
						
					else
						Hum:MoveTo(waypoint.Position)
						Hum.MoveToFinished:Wait()
				end
			end
		end
	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()
	AI.Head.HeadUI: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")
			if patrolPath then
				patrolPath:Destroy()
				patrol()
			end
		else
			lastPos = RP.Position
		end
	end
end

function shoot()
	local target = getTarget()
	
	if target and (target.Character.HumanoidRootPart.Position - RP.Position).Magnitude <= 20 and db == false then
		db = true
		shootTrack:Play()
		shootModule.Shoot(target,Gun,AI)
		
		task.wait(Gun:GetAttribute("FireRate"))
		db = false
	end
end

task.spawn(stuckDetect)


patrol()

as you can see in the video the AI goes over models despite having costs of parts surrounding the models set to math.huge which should make it avoid it, I don’t understand why it does this and it doing so breaks the ai completely and in turn the game

1 Like

How would that fix anything. ………

1 Like

Did you Insert a PathfindingModifier instance onto the part and locate its Label property?

Pathfinding modifiers only have the pass through periphery

You could use raycasts to detect if there is an object between the NPC and the target.

Seems like you didn’t look at the code or watch the video either

I used collision groups to make the parts such that the ai can collide with them but players cant so now they avoid it as intended

I saw the raycast but I didn’t really understnad what it was doing so I thought you were using it for something else possibly.