Detection continues even after the player moves out of sight

When I walk in front of the NPC, it starts to detect me. However, moving out of sight is supposed to start the decreasing of the detection meter. Instead, it keeps on detecting me. I can confirm this isn’t a visual bug, and all prints and functions go through. I’m also receiving no errors.

Video of the issue:

Detection script:

local detectionRange = 30
local npc = script.Parent
local func = game.ServerStorage.Bindables.Alarm
local debounce = false
local LookPart = script.Parent.Detector

local function checkDetection()
	local npcPosition = npc.PrimaryPart.Position
	local npcForward = npc.PrimaryPart.CFrame.LookVector

	local parts = workspace:GetDescendants()
	for _, part in ipairs(parts) do
		if part:IsA("BasePart") and part:FindFirstChild("Suspicious") then
			local direction = (part.Position - npcPosition).Unit
			local angle = math.acos(npcForward:Dot(direction))
			local distance = (part.Position - npcPosition).Magnitude

			if angle <= math.rad(90) and distance <= detectionRange then
				func:Fire("Someone saw something suspicious!")
				break
			end
		end
	end

	for _, player in ipairs(game.Players:GetPlayers()) do
		local character = player.Character
		if character then
			local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
			if humanoidRootPart then
				local direction = (humanoidRootPart.Position - npcPosition).Unit
				local angle = math.acos(npcForward:Dot(direction))
				local distance = (humanoidRootPart.Position - npcPosition).Magnitude

				if angle <= math.rad(90) and distance <= detectionRange then
					local value = game.Players:FindFirstChild(character.Name).Values.Detectable
					if script.Parent.Humanoid.Health ~= 0 then
						if value.Value == true then
							if debounce == false then

								debounce = true
								local i = 5
								local detectlevel = player.Values.DetectLevel
								detectlevel.Value = i

								local ok = true
								repeat 
									if value.Value == true and script.Parent.Humanoid.Health ~= 0 and angle <= math.rad(90) and distance <= detectionRange then
										ok = true
										print(i)
										i -= 1
										detectlevel.Value = i
										task.wait(0.6)
									else
										print("not ok")
										ok = false
										debounce = false
										detectlevel.Value = 5
										break
									end
								until i == 0 or ok == false

								if ok == true then
									func:Fire(player, " was spotted doing something suspicious!")
									break
								end
							end
						end
					end
				end
			end
		end
	end
end

while task.wait() do
	checkDetection()
	wait(1)
end

Thank you in advance!

Please use RunService | Documentation - Roblox Creator Hub instead of while task.wait(), as it is much more common practice to use RunService and can be optimized way more!

One more tip before your actual question, instead of having infinite nests, you should return values that you don’t need, such as instead of your for loop being so extra nested, you can simplify it like this,

for _, player in ipairs(game.Players:GetPlayers()) do
	local character = player.Character
	if not character then
		continue
	end

	local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
	if not humanoidRootPart then
		continue
	end

	local direction = (humanoidRootPart.Position - npcPosition).Unit
	local angle = math.acos(npcForward:Dot(direction))
	local distance = (humanoidRootPart.Position - npcPosition).Magnitude

	if angle > math.rad(90) or distance > detectionRange then
		continue
	end

	local value = game.Players:FindFirstChild(character.Name).Values.Detectable
	if script.Parent.Humanoid.Health == 0 or value.Value ~= true or debounce == true then
		continue
	end

	debounce = true
	local i = 5
	local detectlevel = player.Values.DetectLevel
	detectlevel.Value = i

	local function notOk()
		debounce = false
		detectlevel.Value = 5
	end

	repeat
		if value.Value == true and script.Parent.Humanoid.Health ~= 0 and angle <= math.rad(90) and distance <= detectionRange then
			print(i)
			i -= 1
			detectlevel.Value = i
			task.wait(0.6)
		else
			print("not ok")
			notOk()
			break
		end
	until i == 0

	if i == 0 then
		func:Fire(player, " was spotted doing something suspicious!")
		break
	end
end

Now to your actual question, you are calculating your direction , angle , and distance but then breaking your loop, I suggest returning instead of breaking it so the loop actually continues, which will update the values.

1 Like

Although the issue is already resolved, I would like to mention that what you are looking to achieve could work better if you use raycast

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.