Defining FOV of NPC's vision in a stealth game

I’m having some trouble with the math behind my AI player detection code. I need the the function to return true if the AI is in the line of sight of a player’s head and the player is within the AI’s vision.

The problem is the relativeAngle calculation is incorrect and I can’t figure out why.

function AI:IsInLineOfSight(player)
	if player and player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
		local head = self.Object.Head
		local targetHead = player.Character.HumanoidRootPart
		local ray = Ray.new(head.Position,(targetHead.Position-head.Position))
		local part,point,normal,_ = workspace:FindPartOnRayWithIgnoreList(ray,{head.Parent},true)--workspace.Stuff,
		local relativeRay = self.Object.Head.CFrame:pointToObjectSpace(targetHead + (ray.Direction))
		local AIFacingDirection = head.CFrame.lookVector
		local relativeAngle = math.deg(math.atan2(AIFacingDirection.X,AIFacingDirection.Z) - math.atan2(ray.Direction.X,ray.Direction.Z))
		
		if (relativeAngle > -90 + FOVReduction and relativeAngle < 0) or (relativeAngle > -360 and relativeAngle < -270 - FOVReduction) then
			if part and (part.Parent == targetHead.Parent or part.Parent.Parent == targetHead.Parent) then
				return true
			end
		end
	end
	
	return false
	
end
6 Likes

You can try this tutorial:

8 Likes