How to detect if a player looked at a certain face of a part? Must not work through walls

I’m trying to make a monster in Roblox that will attack you if you look at it’s face. Ideally, this would be to look at it with your player, not your screen.

I wrote a script that detects if your player is facing at the part, and it works great, but it doesn’t take account of walls.

I’ve tried RayCasting, but it was really buggy and only worked if I looked directly at the center of the part. I set the sensitivity to higher, but it really just didn’t work.

This is my facing part code. I would like to somehow make it so it doesn’t work through walls, but I don’t know how.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("Viewed")

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local npc = workspace:WaitForChild("lookpart")

local function CanSee(playerHead, npcHead, maxAngle)
	local lookDirection = playerHead.CFrame.LookVector
	local towardsNpc = (npcHead.Position - playerHead.Position).Unit
	local dotProduct = lookDirection:Dot(towardsNpc)
	local cosineAngle = math.cos(maxAngle)
	return dotProduct >= cosineAngle
end

-- EXAMPLE
game:GetService("RunService").Stepped:Connect(function()
	if CanSee(character.Head, npc, 20) then
		npc.BrickColor = BrickColor.Green()
		RemoteEvent:FireServer(character.Name)
	else
		npc.BrickColor = BrickColor.Red()
	end
end)

Help appreciated.

1 Like

So, it looks like you’ve got math to tell if you are facing the monster, with a given max angle. I think to complete your goal you do need to raycast, but it doesn’t necessarily have to be using the direction that you’re character’s head is facing.

I’d treat it as 2 passes.

  1. Check if it’s in the view cone (you’ve got this)
  2. Check if there is anything obstructing the line of sight between your head and the monster.

For checking line of sight, you can cast a ray from your head to the monster head. (Don’t use the look direction of your head)

2 Likes

That’s a great idea, and it works, however, I still get the issue where I have to be looking directly at the head for it to work.

Is there something I should do to my raycast code?

local SCP096 = game.Workspace:WaitForChild("SCP-096") --// Make sure that the script waits until 096 is out of the ServerStorage
local SCP096Head = SCP096:WaitForChild("Head")
--//  ^^^^^^ SCP-096 is the monster by the way.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("Viewed") --// Find RemoteEvent that triggers when looked

local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()

local PlayerHead = Character:WaitForChild("Head")

while true do
	local Direction = SCP096Head.Position - PlayerHead.Position
	
	local Parameters = RaycastParams.new()
	Parameters.FilterType = Enum.RaycastFilterType.Blacklist --// Make sure these parts don't get in the way. Will make a collision group later
	Parameters.FilterDescendantsInstances = {SCP096:WaitForChild("Jaw"), SCP096Head:WaitForChild("Eyes"), SCP096:WaitForChild("UpperTorso"), SCP096:WaitForChild("LowerTorso"), Character:WaitForChild("Head")}
	
	local RaycastResult = workspace:Raycast(PlayerHead.Position, Direction, Parameters)
	
	if RaycastResult and RaycastResult.Instance then
		if RaycastResult.Instance == SCP096Head then
			print("looked")
		end
	end
	task.wait(0.1) --// Make sure the loop doesnt crash the game
end
1 Like

All of your code looks correct. You might need to hone in on exactly where the code isn’t working as expected.

Some things I’d suggest:

  • Double check that you are using radians for maxAngle
  • Raycast only ignore player character, and ignore the entire character, not just the head.
  • Raycast accept a hit that hit:IsDescendantOf(SCP096)
  • Make print statements to continually to see the result of these features (and in a nice controlled environment)
2 Likes

It turned out the Ray was hitting my players hat! lol… thank you for the help!

2 Likes

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