public bool SeeGameObject(GameObject go)
{
// if object has a renderer and visible by any camera and is in this camera frustum
if(go.renderer != null && go.renderer.isVisible && GeometryUtility.TestPlanesAABB(GeometryUtility.CalculateFrustumPlanes(_camera), go.renderer.bounds))
{
RaycastHit hitInfo;
// by default we use the rough renderer bounds
Vector3 center = go.renderer.bounds.center;
Vector3 extents = go.renderer.bounds.extents;
float coefreduc = 0.8f;
Vector3[] gobounds; // points to check for linecast from camera
MeshFilter meshfilter = go.GetComponent<MeshFilter>();
if(meshfilter != null) // Almost every interesting game object that is render has a mesh
{
center = go.transform.position;
extents = meshfilter.mesh.bounds.extents;
extents.Scale(go.transform.lossyScale);
gobounds = new Vector3[33]{ // We can add more or remove some, it increase precision for not too much time or memory cost
Vector3.zero,
go.transform.TransformDirection(new Vector3(extents.x,extents.y,extents.z)*0.9f),
go.transform.TransformDirection(new Vector3(extents.x,extents.y,-extents.z)*0.9f),
go.transform.TransformDirection(new Vector3(extents.x,-extents.y,extents.z)*0.9f),
go.transform.TransformDirection(new Vector3(extents.x,-extents.y,-extents.z)*0.9f),
go.transform.TransformDirection(new Vector3(-extents.x,extents.y,extents.z)*0.9f),
go.transform.TransformDirection(new Vector3(-extents.x,extents.y,-extents.z)*0.9f),
go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,extents.z)*0.9f),
go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,-extents.z)*0.9f),
go.transform.TransformDirection(new Vector3(extents.x,extents.y,extents.z)*0.5f),
go.transform.TransformDirection(new Vector3(extents.x,extents.y,-extents.z)*0.5f),
go.transform.TransformDirection(new Vector3(extents.x,-extents.y,extents.z)*0.5f),
go.transform.TransformDirection(new Vector3(extents.x,-extents.y,-extents.z)*0.5f),
go.transform.TransformDirection(new Vector3(-extents.x,extents.y,extents.z)*0.5f),
go.transform.TransformDirection(new Vector3(-extents.x,extents.y,-extents.z)*0.5f),
go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,extents.z)*0.5f),
go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,-extents.z)*0.5f),
go.transform.TransformDirection(new Vector3(extents.x,extents.y,extents.z)*0.75f),
go.transform.TransformDirection(new Vector3(extents.x,extents.y,-extents.z)*0.75f),
go.transform.TransformDirection(new Vector3(extents.x,-extents.y,extents.z)*0.75f),
go.transform.TransformDirection(new Vector3(extents.x,-extents.y,-extents.z)*0.75f),
go.transform.TransformDirection(new Vector3(-extents.x,extents.y,extents.z)*0.75f),
go.transform.TransformDirection(new Vector3(-extents.x,extents.y,-extents.z)*0.75f),
go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,extents.z)*0.75f),
go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,-extents.z)*0.75f),
go.transform.TransformDirection(new Vector3(extents.x,extents.y,extents.z)*0.25f),
go.transform.TransformDirection(new Vector3(extents.x,extents.y,-extents.z)*0.25f),
go.transform.TransformDirection(new Vector3(extents.x,-extents.y,extents.z)*0.25f),
go.transform.TransformDirection(new Vector3(extents.x,-extents.y,-extents.z)*0.25f),
go.transform.TransformDirection(new Vector3(-extents.x,extents.y,extents.z)*0.25f),
go.transform.TransformDirection(new Vector3(-extents.x,extents.y,-extents.z)*0.25f),
go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,extents.z)*0.25f),
go.transform.TransformDirection(new Vector3(-extents.x,-extents.y,-extents.z)*0.25f)
};
}
else // Only if gameobject has no mesh (= almost never) (Very approximately checking points using the renderer bounds and not the mesh bounds)
{
gobounds = new Vector3[9]{
Vector3.zero,
new Vector3(extents.x,extents.y,extents.z)*coefreduc,
new Vector3(extents.x,extents.y,-extents.z)*coefreduc,
new Vector3(extents.x,-extents.y,extents.z)*coefreduc,
new Vector3(extents.x,-extents.y,-extents.z)*coefreduc,
new Vector3(-extents.x,extents.y,extents.z)*coefreduc,
new Vector3(-extents.x,extents.y,-extents.z)*coefreduc,
new Vector3(-extents.x,-extents.y,extents.z)*coefreduc,
new Vector3(-extents.x,-extents.y,-extents.z)*coefreduc
};
}
foreach(Vector3 v in gobounds)
{
// test if it can see gameobject
if(GeometryUtility.TestPlanesAABB(GeometryUtility.CalculateFrustumPlanes(_camera), new Bounds(v+center, Vector3.zero)) // if point in viewing frustrum
&& (!Physics.Linecast(transform.position, v+center, out hitInfo) || hitInfo.collider.gameObject == go )) // if nothing between viewing position and point
{
if(graphicalDebug)
{
Debug.DrawLine(transform.position, v+center,Color.red, 0.01f, false);
}
return true;
}
}
}
return false;
}