[NEEDS TO BE FIXED] Need help on this AI (pathfinding)

This is a script that handles all of the pathfinding an AI for a monster
The monster has 2 states: Walking and Chasing

When the monster is walking, there is no player nearby, and they are walking to random waypoints.
When the monster is chasing, they just chase the player.

However, the problem is that the overall AI is sometimes buggy
These are the 2 Main Problems:

  1. When the monster finds a player through a wall, they start bugging out

  2. When the monster is chasing a player, they sometimes turn around for a second

EXTRA INFO: The blue means the AI is using a MoveTo() to get to the player, the red means the AI is using Pathfinding to get to the player

code:



local npc = script.Parent
local human = npc.Humanoid
local hrp = npc:WaitForChild("HumanoidRootPart")

local PFS = game:GetService("PathfindingService")
local RUNSERVICE = game:GetService("RunService")

local RaycastHitbox = require(game:GetService("ReplicatedStorage").RaycastHitboxV4)
local Params = RaycastParams.new()
Params.FilterType = Enum.RaycastFilterType.Blacklist
Params.FilterDescendantsInstances = {npc} 

local newHitbox = RaycastHitbox.new(script.Parent.Knife)
newHitbox.RaycastParams = Params
RaycastHitbox.DetectionMode = 1
--task.wait()


local AttackCooldown = .75
local HitDebounce = false
local AttackDebounce = false
local MaxAttackDistance = 3

local SwingSounds = npc.AttackZone.SwingSounds:GetChildren()
local HitSounds = npc.AttackZone.HitSounds:GetChildren()

local destination = workspace.CampingPath:GetChildren()

local IsAttacking = npc.IsAttacking

local foundtarget = nil

local SpawnIdle = human.Animator:LoadAnimation(script.Parent.SpawnIdle)
local SpawnAnim = human.Animator:LoadAnimation(script.Parent.Spawn)

--SpawnIdle:Play()

workspace.Values.EnableCamping.Changed:Wait()
print("CAMPING MONSTER ENABLED")
--SpawnIdle:Stop()
--SpawnAnim:Play()

--SpawnAnim.Stopped:Wait()
--[[
newHitbox.OnHit:Connect(function(hit, humanoid, hum) 
	if HitDebounce == false then
		HitDebounce = true
		local RandomHitSound = HitSounds[math.random(1, #HitSounds)]
		print(humanoid)
		RandomHitSound:Play()
		humanoid:TakeDamage(10)
		print("hit")
		newHitbox:HitStop()
		task.wait(AttackCooldown)
		HitDebounce = false
	end
end)	
--]]

local Attack1Anim = human.Animator:LoadAnimation(script.Parent.Attack)
local Attack2Anim = human.Animator:LoadAnimation(script.Parent.Attack2)
local WalkAnim = human.Animator:LoadAnimation(script.Parent.Walk)
local RunAnim = human.Animator:LoadAnimation(script.Parent.Run)

local SpeedTween = game:GetService("TweenService"):Create(human, TweenInfo.new(2.5), {WalkSpeed = 20})


human.Running:Connect(function(speed)
	if speed > 15 then
		RunAnim:Play()
		WalkAnim:Stop()
	elseif speed < 10 then
		WalkAnim:Play()
		RunAnim:Stop()
	end
end)

Attack1Anim.Stopped:Connect(function()
	newHitbox:HitStop()
end)
Attack2Anim.Stopped:Connect(function()
	newHitbox:HitStop()
end)

npc.PrimaryPart:SetNetworkOwner(nil)


local points = {}
for _,part in ipairs(destination) do
	table.insert(points,part)
	task.wait()
end

local walkDebounce = false

function walkRandomly()
if walkDebounce == false and foundtarget == nil then
walkDebounce = true
print(walkDebounce)
	--IsAttacking.Value = false
	local point = points[math.random(1,#points)]
	--local target = FindTarget()
	local path = game:GetService("PathfindingService"):CreatePath({
		AgentRadius = 2,
		AgentHeight = 5,
		AgentCanJump = true,
		Costs = {
			PathFindingModifier = math.huge
		}
	})
	path.Blocked:Connect(function()
		path:Destroy()
		print("DEBUG: PATH BLOCKED (WALKRANDOMLY)")
		walkRandomly()
	end)
	path:ComputeAsync(hrp.Position, point.Position)

	local waypoints = path:GetWaypoints()
	for _, waypoint in ipairs(waypoints) do
		if foundtarget == nil then
			--print("DEBUG: WALKING RANDOMLY TO WAYPOINT")
			--IsAttacking.Value = false
			human:MoveTo(waypoint.Position)
			IsAttacking.Value = false
			foundtarget = nil
			human.WalkSpeed = 8
			path.Blocked:Connect(function()
				path:Destroy()
				print("DEBUG: PATH BLOCKED (WALKRANDOMLY)")
				walkRandomly()
			end)
			if waypoint.Action == Enum.PathWaypointAction.Jump then
				human:ChangeState(Enum.HumanoidStateType.Jumping)
			end
		end
		if IsAttacking.Value or foundtarget == 1 then path:Destroy() break end
		human.MoveToFinished:Wait()
		--FindTarget()
	end

	if path.Status == Enum.PathStatus.Success and foundtarget == nil then
		print('Success!')
		walkDebounce = false
	end
	end
end


local Swings = 0

local function findTarget()
	--print('should run every frame 2')
	local players = game:GetService("Players"):GetPlayers()
	local nearesttarget
	local maxDistance = 25 -- distance
	for i,player in pairs(players) do
		if player.Character then
			local target = player.Character
			local distance = (npc.HumanoidRootPart.Position - target:WaitForChild("HumanoidRootPart").Position).Magnitude
			if distance < maxDistance  then
				nearesttarget = target
				maxDistance = distance
				--print(target)
				--print("Found target, nearesttarget = target")
			end
			task.spawn(function()
			local humanoid = target.Humanoid
			if distance <= MaxAttackDistance and not AttackDebounce then
				--
				AttackDebounce = true
				if Swings == 0 then
				Attack1Anim:Play()
				Swings += 1
				else
					Attack2Anim:Play()
					Swings = 0
				end
				--newHitbox:HitStart()
				local RandomSwingSound = SwingSounds[math.random(1, #SwingSounds)]
				RandomSwingSound:Play()
				if HitDebounce == false then
					HitDebounce = true
					local RandomHitSound = HitSounds[math.random(1, #HitSounds)]
					print(humanoid)
					RandomHitSound:Play()
					--humanoid:TakeDamage(10)
					print("hit")
					--newHitbox:HitStop()
					task.wait(AttackCooldown)
					HitDebounce = false
				end
				task.wait(AttackCooldown)
				AttackDebounce = false--
			end
			end)
			
		end
	end
	return nearesttarget
end

local function getPath(destination)
	local path = PFS:CreatePath()

	path:ComputeAsync(npc.HumanoidRootPart.Position, destination)

	return path
end
local function CheckRaycast()
	local target = findTarget()
	if target then
		local ray = Ray.new(npc.HumanoidRootPart.Position,(target.HumanoidRootPart.Position - npc.HumanoidRootPart.Position).unit * 100) -- create the ray
		local hit,pos = workspace:FindPartOnRay(ray,npc) -- find parts that the ray hit
		if hit then -- if the ray hit a part then
			--[[
			local distance = (npc.HumanoidRootPart.Position - pos).Magnitude
			local p = Instance.new("Part")
			p.Anchored = true
			p.CanCollide = false
			p.Size = Vector3.new(1.1, 1.1, distance)
			p.CFrame = CFrame.lookAt(pos, npc.HumanoidRootPart.Position)*CFrame.new(0, 0, -distance/2)
			p.Parent = workspace
			--]]
			if hit:IsDescendantOf(target) then -- if the part is part of the target's character then
				--foundtarget = 1
				return true -- return true
			end
		end
		--IsAttacking.Value = false
		--foundtarget = nil
		return false -- if no target was found, return false
	end
end


local function pathFindTo(destination)
	local path = getPath(destination)
	local target = findTarget()


	path.Blocked:Connect(function()
		path:Destroy()
	end)


if target and target.Humanoid.Health > 0 then
	for i,waypoint in pairs(path:GetWaypoints()) do

		if waypoint.Action == Enum.PathWaypointAction.Jump then
			human.Jump = true
		end
		IsAttacking.Value = true
		foundtarget = 1
		human.WalkSpeed = 18
		if CheckRaycast() == false then
			npc.Highlight.FillColor = Color3.fromRGB(255, 0, 0)
			--print("Using Pathfinding, Should just be this printing")
		human:MoveTo(waypoint.Position)
		human.MoveToFinished:Wait()
		else
			npc.Highlight.FillColor = Color3.fromRGB(0, 0, 255)
			human:MoveTo(target.PrimaryPart.Position)
			task.wait()
			--print("Using Basic MoveTo(), Should just be this printing")
		end
--[[
if CheckRaycast() == true then -- you're going to have to make your own checkraycast function
	repeat
		human:MoveTo(target.PrimaryPart.Position)
		task.wait()
		print("Using Basic MoveTo(), Should just be this printing")
	until CheckRaycast() == false
	break
end
--]]
	end
end
end




while true do
	task.wait()
	--print('every frame bruh')
	local target = findTarget()
	task.spawn(function()
		if target then
			--print("Attacking"..target.Name)
			--print('attackin')
			pathFindTo(target:WaitForChild("HumanoidRootPart").Position)
		else
			--print('walking')
			walkRandomly()
		end

	end)
	
	CheckRaycast()	
end



Try this.

for i,v in pairs(script.Parent:GetDescendants()) do
   if v:IsA("BasePart") and v:CanSetNetworkOwner() then
    v:SetNetworkOwner(nil)
end
end

(i just realized i forgot to put the code)
in the video you can tell that 1 and 2 are scripting issues, nothing to do with network owner

I know, and yet sometimes this script can fix jittery pathfinding.

this still needs to be fixed :sob::sob::sob::sob:

Maybe stop the NPC from pathfinding when it’s close to it’s target & no ray is hit between the player & NPC.

thats what it does in the code

(see the video)

still need help on this, mostly problem 2.