I’m building some detection code: there are a bunch of cameras, which are not enabled. I want to know if any of them can see an object. It’s a bit like surveillance cameras, I suppose - if this camera can see the player object, say, trip an alarm.
There seem to be various gotchas with using things like renderer.isVisible and so on - especially since I need it to be for specific cameras, not the main renderer. I’ve just tried out one that looked promising - it calculates the frustrum planes of the camera, and then uses TestPlanesAABB to check.
Problem is, this checks if the entire frustrum contains the object, regardless of whether the object is actually visible, i.e. it ignores solid objects between detectionTarget and the camera.
What can I do to enhance the check to make sure it only reacts to things it can actually see? One idea I had was to raycast from the object. This isn’t perfect though, as if the object is large or shaped oddly, it might actually be visible even though its centerpoint isn’t.
First thought off the top of my head. (it’ll do exactly what you want, its expensive but honestly it might not matter if your not doing the operation on dozens of cameras at once)
when within camera frostum and within detection distance
for each vertice in the mesh cast an array from the camera to the vertice.
Now its very precise, if any part is sticking out in the slightest it will be caught.
// The raycast positions relative to player
public Vector3 top = new Vector3(0, 1, 0);
public Vector3 mid = new Vector3(0, 0, 0);
public Vector3 bot = new Vector3(0, -1, 0);
public float rayDistance = 500f;
public Transform player
Renderer playerRenderer;
void Start(){
playerRenderer = player.GetComponent<Renderer>();
}
void LateUpdate(){
if(!playerRenderer.isVisible)
return; // No camera is rendering
GameObject camera;
if(TryRaycastPlayer(camera, top) || TryRaycastPlayer(camera, mid) || TryRaycastPlayer(camera, bot))
Debug.Log("I can see you!");
}
bool TryRaycastPlayer(out GameObject g, Vector3 relativeTo) {
g = null;
Vector3 to = player.TransformPoint(relativeTo);
Vector3 direction = player.position - to;
direction.Normalize();
// Check if can see the point
RaycastHit hit;
if(Physics.Raycast(transform.position, direction, rayDistance, hit)){
g = hit.gameObject;
return true;
}
return false;
}
I’ve not tested it but it should work, let me know if is right