Detect if player is looking at object

I want to detect if a part is in the players general field of view. Ive tried raycasting but I have no idea how to use it and WorldToViewportPoint detect it through walls. Any help would be amazing

There are a lot of resources about this and is probably the best way if you don’t want it to happen through walls.

https://developer.roblox.com/en-us/api-reference/function/WorldRoot/Raycast

thats the exact video I looked at XD I don’t understand how I can do that for the players head though

Good question, and you’ve got pretty much the exact right idea already. Use WorldToViewportPoint to first check if it’s on-screen at all, and then raycast from that position toward the object to see if it hits anything. If both checks pass, then the player can see the object.

Just note, there’s a caveat to this: It ​isn’t perfect, because it’s just point-checking. In other words, we’re just checking if one point of the object is visible. We would have to do a ton of raycasting to check if any part of the object is visible.

But this is roughly how it would be done:

-- LocalScript

local partToCheck = workspace.SomePart
local camera = workspace.CurrentCamera

-- Check if on screen:
local vector, inViewport = camera:WorldToViewportPoint(partToCheck.Position)
local onScreen = inViewport and vector.Z > 0

-- Raycast outward:
local ray = camera:ViewportPointToRay(vector.X, vector.Y, 0)
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.FilterDescendantsInstances = {partToCheck, game.Players.LocalPlayer.Character}
local raycastResult = workspace:Raycast(ray.Origin, ray.Direction * 1000, raycastParams)

-- Final check:
local isVisible = onScreen and not raycastResult
if isVisible then
   -- Do something
end
1 Like

it came up with this error any idea what it means?
attempt to perform arithmetic (mul) on Ray and number

Try it now. I used ray.Unit on accident. Should have been ray.Direction.

now theres no error but it just doesn’t print

-- LocalScript

local partToCheck = workspace.SomePart

local camera = workspace.CurrentCamera

-- Check if on screen:

local vector, inViewport = camera:WorldToViewportPoint(partToCheck.Position)

local onScreen = inViewport and vector.Z > 0

-- Raycast outward:

local ray = camera:ViewportPointToRay(vector.X, vector.Y, 0)

local raycastParams = RaycastParams.new()

raycastParams.FilterType = Enum.RaycastFilterType.Blacklist

raycastParams.FilterDescendantsInstances = {partToCheck, game.Players.LocalPlayer.Character}

local raycastResult = workspace:Raycast(ray.Origin, ray.Direction * 1000, raycastParams)

-- Final check:

local isVisible = onScreen and not raycastResult

while true do

wait()

if isVisible then

print("works")

end

end

The isVisible variable won’t magically update itself. You need to call the remainder of the code every time. You could do this by wrapping it in a function:

local function IsVisible()
   -- The code I wrote before
   return isVisible
end

while true do
   task.wait()
   local isVisible = IsVisible()
   if isVisible then
      print("visible")
   else
      print("not visible")
   end
end
2 Likes

thanks a ton. This really helped me.

1 Like