NPC entering Pathfinding phase when totally uncalled for

Currently trying to figure out why this NPC follows me as it should for a few seconds, then it randomly enters its Pathfinding phase.

https://puu.sh/IKais/a1327a8259.mp4

The NPC will approach the player if they are within 24 studs, then it starts to follow them, but on top of that, it also fires a raycast every second, to check for obstructions (this means two loops at the same time, also not sure if I’m doing this in the right way, so please let me know xd).

The problem happens here, as it finds obstructions that are not even there. The script goes as follows:

local function scan(currentTarget)
	local raycastParams = RaycastParams.new()
	raycastParams.FilterDescendantsInstances = {
		game.Players:FindFirstChild(currentTarget).Character, 
		char
	}
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
	local result = workspace:Raycast(char.Torso.Position, game.Players:FindFirstChild(target.Value).Character.Torso.Position, raycastParams)
	
	local p1 = Instance.new("Part")
	p1.Position = char.Torso.Position
	p1.Shape = "Ball"
	p1.Anchored = true
	p1.CanCollide = false
	p1.CanTouch = false
	p1.CanQuery = false
	p1.Size = Vector3.new(1,1,1)
	p1.BrickColor = BrickColor.new("New Yeller")
	
	local p2 = Instance.new("Part")
	p2.Position = game.Players:FindFirstChild(target.Value).Character.Torso.Position
	p2.Shape = "Ball"
	p2.Anchored = true
	p2.CanCollide = false
	p2.CanTouch = false
	p2.CanQuery = false
	p2.Size = Vector3.new(1,1,1)
	p2.BrickColor = BrickColor.new("New Yeller")

	local distance = (char.Torso.Position - game.Players:FindFirstChild(currentTarget).Character.Torso.Position).Magnitude
	
	local p = Instance.new("Part")
	p.Anchored = true
	p.CanTouch = false
	p.CanCollide = false
	p.CanQuery = false	
	p.Size = Vector3.new(0.5, 0.5, distance)
	p.BrickColor = BrickColor.new("New Yeller")
	p.CFrame = CFrame.lookAt(char.Torso.Position, game.Players:FindFirstChild(target.Value).Character.Torso.Position)*CFrame.new(0, 0, -distance/2)
	
	wait()
	
	p.Parent = workspace
	p1.Parent = workspace
	p2.Parent = workspace

	if result then
		print("Found obstruction!")
		stuck.Value = true
	end
	
	wait(1)
	p:Destroy()
	p1:Destroy()
	p2:Destroy()
	
end

local function chase()
	local currentTarget = target.Value
	print(currentTarget)
	coroutine.resume(coroutine.create(function()
		while target.Value == currentTarget and stuck.Value == false do
			wait()
			char.Humanoid:MoveTo(game.Players:FindFirstChild(currentTarget).Character.Torso.Position)
			local distance = (char.Torso.Position - game.Players:FindFirstChild(target.Value).Character.Torso.Position).Magnitude
			if distance > minimumDistance * 2 then
				target.Value = ""
			end
		end
	end))
	while target.Value == currentTarget and stuck.Value == false do
		scan(target.Value)
		--wait(1)
	end
end

local function find()
	print("Spawning part")

	local offset = Vector3.new(0,0,12)

	local temp = Instance.new("Part")
	temp.Transparency = 1
	temp.Anchored = true
	temp.Position = char.Torso.Position
	temp.CFrame = char.Torso.CFrame*CFrame.new(offset)
	temp.CanCollide = false
	temp.CanTouch = false
	temp.CanQuery = false
	temp.Parent = workspace

	wait()

	char.Humanoid:MoveTo(temp.Position)
	temp:Destroy()
	wait(0.2)

	local toChase = game.Players:FindFirstChild(target.Value).Character

	print("Attempting to chase player: " .. toChase.Name)

	local path = pfService:CreatePath({
		WaypointSpacing = math.huge -- maybe with each inflection point fire moar raycasts
		-- this way you can check if pathfinding state is worth still running
	})

	path:ComputeAsync(char.Torso.Position, toChase.Torso.Position)

	local waypoints = path:GetWaypoints()

	print("Path status: " .. tostring(path.Status))
	print("Generated " .. #waypoints .. " waypoints.")

	for i, v in pairs(waypoints) do
		if v.Action == Enum.PathWaypointAction.Jump then
			if jumped == false then
				char.Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
			else
				repeat wait() until jumped == false
				char.Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
			end
		end
		char.Humanoid:MoveTo(v.Position)
		char.Humanoid.MoveToFinished:Wait(2)
		if i == #waypoints then
			print("Target reached.")
			stuck.Value = false
		end
	end

end

These functions are called based on the signal that I’m very primitively using in order to detect any changes (plz no judging, if there’s a better way of doing this tell me!!):

signal.Changed:Connect(function()
	if signal.Value == true then
		print("Received ping!")
		if stuck.Value == false and target.Value == "" then
			print("Idling...")
			idle()
		elseif stuck.Value == false and target.Value ~= "" then
			if behavior.Value == "Hostile" or behavior.Value == "Neutral" then
				print("Chasing...")
				chase()
			elseif behavior.Value == "Friendly" or behavior.Value == "Asocial" then
				print("Fleeing...")
				flee()
			end
		elseif stuck.Value == true and target.Value ~= "" then
			print("Finding...")
			find()
		end
	end
end)

I have tried pretty much anything I could think of, I tried blacklisting the character and the chased character, visualizing the raycast (even disabling CanQuery too), spamming waits everywhere, even casually rewriting this script for the third time. If there is something I missed, please let me know!!

This is a long script so I’m not going to go over all of it however, what I think you’ve done is that as soon as you get out of the range of the NPC it stops and then the system malfunctions somewhere not by an error but a value on a while loop or if statement has changed meaning that the loop is not repeating.

I’d recommend going over the script and take a look at the values which affect this area of the script
while target.Value == currentTarget and stuck.Value == false do
PS: You might also need to return the values

The getaway range is double the detection range. For the player to be detected, it has to be within 24 studs. For the player to escape the NPC, however, the distance has to be 48 studs.

Before I look for any malfunctions, I first need to understand why does it even find an obstruction in literally nothing… The loops are meant to stop repeating once either value changes, because that means it is ready to send a signal and change the NPC’s behavior.

But do they really stop repeating, or do they just pause?

Whenever I’m in your position I use

Print("Gone through")

And then I’ll put this in a part of the code to see if its running
So for example put the print function inside chase() just above :move to, and keep on moving it about and try and see why the code isn’t running.

You are missing the main problem. It’s not that the character stops moving after Pathfinding, it’s that the raycast is obstructed for some odd reason. I can definitely troubleshoot that later on, it’s not as difficult as the current issue.

I’ll rewrite the code for the 4th time, maybe from scratch this time, since the lines I used is basically a compilation of what I previously tried to do. I’m getting lost in my own code. Trial and error ftw!!

Feel free to still suggest any solutions though. This thread will stay opened

Hey, bumping just to let everyone know that I found a solution - limiting the ray length to 24 studs, the same required distance for the NPC to detect a player. Use Vector3.Unit! :grin: