Detect if entity is visible - renderer.isvisible will not work!

To put it simply, I need to detect if an entity/it’s children are visible or not by the camera. I’ve been using renderer.isvisible, however it simply won’t work. It’s extremely glitchy- sending off signals that it isn’t visible when it’s right in-front of the camera, and thinks it is visible when it’s no-where in sight. I’ve been digging for the past few weeks for a solution, and all that I’ve found is something to do with GeometryUtility.TestPlanesAABB to check if it’s visible- but can’t figure out quite how. The example on the Unity page even says it detects if it’s visible, but I’ve had absolutely no luck in getting it to work- even in an new empty script. An alternative, or a working example that I could throw in here would be amazing; I don’t care what it is, as-long as it’s precise.

TL~DR: I need a way to precisely detect if an object is visible or not. Doing it by renderer is horrible unstable/un-precise and will not work for this project.

Any help would be greatly appreciated, as I can’t continue any further on my project without a solution to this. I’d also like to mention that my entire project is in JavaScript, and I do not understand more than basic syntax of C#.

renderer.isVisible works fine, but it actually only tells whether the object is inside the viewing angle of any camera (including the scene view’s camera). It doesn’t know if an object is being obscured by another one - a character completely behind a wall still reports isVisible = true if in front of any camera. You can use the events OnBecameVisible/OnBecameInvisible instead: they are called whenever isVisible changes state to true/false.

The isVisible property probably is set by the frustum culling process, which takes place when a camera is about to render the scene: all objects are tested against the frustum planes with an internal version of TestPlanesAABB (actually, their renderer.bounds are tested).

If you must know whether an object is inside the viewing frustum of one specific camera only (ignoring other cameras), the test must be made manually (attach this to the object):

function Update() {
	var planes: Plane[] = GeometryUtility.CalculateFrustumPlanes(Camera.main);
	if (GeometryUtility.TestPlanesAABB(planes,renderer.bounds))
		Debug.Log("Object inside frustum");
	else
		Debug.Log("Object not visible");
}

But if you must know whether the object is obscured, things get way more complicated - actually, there’s no reasonable way to check if any pixel of the object is visible (maybe analyzing the depth buffer with some specialized shader).

I have/had this problem. If it’s not the scene view, it’s probably the shadow. While IsVisible works pretty accurate for geometry itself, the shadow can turn it to true even if is still far outside of the camera’s view. I guess there is very rough estimation whether a shadow should be visible that tends to be on the safe side rather than accurate. Try deactivating shadows on your geometry to test if that’s the issue.

My workaround is to hide a tiny cube with no shadow inside the geometry and test IsVisible for the cube’s renderer instead of the original mesh’ one. It’s a bit clunky, but basically works for me.
You could also make the cube/sphere as big as you want and make its material transparent.

As a workaround, you could do raycasts every few frames against all relevant gameobjects in the scene (possible if there’s not too many at once):

var fov : float = 45.0;
LoSBlockMask : LayerMask;
hit : RaycastHit;

function CheckLineOfSight (target : GameObject) : boolean 
{
	if (Vector3.Angle(target.transform.position - transform.position, transform.forward) <= fov)
    {
    	if(Physics.Linecast(transform.position, target.transform.position, hit, LoSBlockLayerMask) == false)
    	{
             //target is inside fov and a line from the player's front towards the target's origin is not interrupted by los-blocking obstacles specified in LoSBlockMask
        }
     }
}