How to check if player sees an entity?

Hello, Facepunch.

I was wondering how to check if player sees an entity in Lua?


Maybe use this?


No, that’s not what i want. I’m writing some kind of SCP-173 that will kill players when noone sees it. This method is bad because it returns true if position of an entity can be seen from position of another entity. Even if player stands with his back to another entity this will still return true.

Then use this


You can check if the entity they are looking at is the entity you want, this works based on where there crosshair is looking.

If player will move away his crosshair from the entity so that it’s still on player’s screen, this will return false. That’s not what i want, i need it to return true when entity renders on player’s screen and return false if entity is completely hidden from the player’s view.

Since this didn’t work, maybe this might be what you’re looking for? The docs make it sound like what you’re looking for.



ents.FindInCone could work, if it works as I understand it

Or the above thing

  1. Trace a line from the players eyes (ply:ShootPos()) and return true if the hit is the entity.

A2) Use

ents.FindInCone check if the entity is infront of the player
B2) Check the yaw/pitch difference between (Ent:GetPos() - Ply:ShootPos()):Angle() (Angle towards the entity) and

Entity:EyeAngles with

math.AngleDifference. return true if the pitch- and yaw-difference are within -90 to 90 degrees (or less)

if any of them are false, the person are not watching the entity.

Protip #1: Only run the second thing, if the first is true. 1) is cheaper than 2A/2B)
Protip #2: Run this at max every second, as it gets expensive to run it in Think.

Could also do

local eyeToMonster = (monster:GetPos() - player:EyePos()):GetNormalized() -- Normalized direction to the monster
local degreeLimit = player:GetFOV() -- FOV
local dotProduct = eyeToMonster:Dot(player:EyeAngles():Forward()) -- How similar is the player's aim direction to the direction of the monster?
local aimDegree = math.deg(math.acos(dotProduct)) -- Convert similarity to degrees

-- If the degree difference in similarity is bigger than the player's FOV, then most likely it isn't being rendered
if (aimDegree >= degreeLimit) then
	-- they're not on the player's screen anymore, do something!

Or you could even use a and

Vector:ToScreen together.

The problem with ToScreen, is its a clientside function. Any scriptkiddies would be able to edit the detection and walk around unnoticed when networking the data.

Couldn’t you frustum cull the player’s view plane and check if a corner of the entity’s bounding box lies in the pyramid?

-snip, bad reader-

I’m sorry for not responding for so long. I’m going with method Z0mb1n3 mentioned.

Thanks everyone.