Check if any character is in sight of an NPC

I want to know how i could i check if a character is in view of an NPC, I was using dotProduct but that still finds it if its behind a wall. how could i do this?

local Players = game:GetService("Players")

local AttackModule = {}

function AttackModule.FindTarget(HeadPart)
	for i, Model in pairs(game.Workspace:GetChildren()) do
		if Model:IsA("Model") and Model:FindFirstChild("Humanoid") and Model ~= HeadPart.Parent then
			
			print("yes")
			local PlrCharacter = Model

			if PlrCharacter then

				local PlrHead = PlrCharacter:WaitForChild("Head")

				if PlrHead then
					local NpcToCharacter = (PlrHead.Position - HeadPart.Position).Unit
					local NpcLookVector = HeadPart.CFrame.LookVector
					print(NpcToCharacter)

					local DotProduct = NpcToCharacter:Dot(NpcLookVector)
					print(DotProduct, PlrCharacter)
					if DotProduct > 0.4 then
						print("OK")
						return true
					end
				end

			end

		end
	end
end

return AttackModule

Try using raycasting to check if the player is behind an object.

3 Likes

Dot is incredibly helpful for this, and you’re right to use it. I’d recommend utilizing Raycasting to detect if there’s anything obstructing the NPC’s view. Just to be clear, you should still be using Dot for this, and you’re just going to be utilizing Raycasts ontop of this.

This can be done with something as simple as

local Distance : number = 50 -- this is how far you want their vision to go

if DotProduct > 0.4 then
	local RayToCharacter = workspace:Raycast(NPC.HumanoidRootPart, (PlrCharacter.HumanoidRootPart - NPC.HumanoidRootPart).Unit * Distance) -- be sure to include RaycastParams by the way!
	if RayToCharacter then
		if RayToCharacter.Instance:FindFirstAncestorOfClass("Model") == PlrCharacter then
			return true
		end
	end
end
1 Like

Just for some further context, the reason I’m using RayToCharacter.Instance:FindFirstAncestorOfClass("Model") to detect if it hits the Player’s Character is because there’s no guarentee that it’ll directly hit someone’s HumanoidRootPart, and we should be accounting for all limbs. Let’s say we hit a Character’s “Right Arm” with the Raycast. We can then find it’s :FirstAncestorOfClass("Model"), and if it’s our Character, then it’s go time.

1 Like

Yes I think this is your best approach. Iterate through all the players’ characters with a raycast.

1 Like

That works perfectly, I was thinking about using raycasting but I didnt know how it would turn out.