4
\$\begingroup\$

I want to check if a GameObject is visible to the camera. The renderer.isVisible-method only checks if the camera is turned towards the object, not if there is anything between them (like a wall).

How can I check whether the object is actually visible?

\$\endgroup\$
8
\$\begingroup\$

As requested, one possible solution (with some flaws) is to use raycasting:

Attaching a (C#) Script similar to this to the GameObject from which you want to check visibility would work:

if(renderer.isVisible) //Check if Camera is turned towards the GameObject first
{
   RaycastHit hit;
   // Calculate Ray direction
   Vector3 direction = Camera.main.transform.position - transform.position; 
   if(Physics.Raycast(transform.position, direction, out hit))
   {
      if(hit.collider.tag != "MainCamera") //hit something else before the camera
      {
         //do something here
      }
   }
}

The flaws of this approach:

  • Every object that could be in between the GameObject and the Camera has to have a collider attached to it.
  • This approach may produce false negatives in the case of partially obstructed objects, as the ray is cast from the center point of your object. If this is a problem in your case, then you may have to work around it (for example, by casting multiple rays from different positions).
\$\endgroup\$
  • \$\begingroup\$ Rather than testing the center point of the object this is checking the position of its transform i.e. for some some humanoid characters this may be the bottom of their feet. In these cases renderer.bounds.center can be useful. \$\endgroup\$ – Kelly Thomas Oct 15 '14 at 0:10
  • \$\begingroup\$ this will cause serious poping issues. I don't know of any profesional engine that uses this method. \$\endgroup\$ – v.oddou Oct 15 '14 at 1:57
  • \$\begingroup\$ Used this code. Sadly, it doesn't check if the camera can see any part of the GameObject, it only checks its position. Is there a way to check if camera can see any part of the object at all? \$\endgroup\$ – Bitcoin M Oct 15 '14 at 3:33
  • 1
    \$\begingroup\$ @Bitcoin M I remember seeing a video of a game (think it was 'Overgrowth') that used rays periodically cast from the camera/avatar to a random point over the bounding box of another object which was used to determine 'cover'. i.e. if, for example, there were 10 rays per second and all of them collided with the target object then it was completely unobstructed, if 1 of 10 collided then it was mostly obstructed. Was used for AI if I recall correctly. \$\endgroup\$ – DFreeman Oct 15 '14 at 9:50
5
\$\begingroup\$

Depending on your exact needs, another possible solution would be to do a test render where you set different objects to different colors and then check for that color in the test render.

However this would only be useful in pretty obscure situations; in the majority of situations I would use raycasting. I'm just dropping in this different answer for completeness in considering all your options.

\$\endgroup\$
  • 1
    \$\begingroup\$ Exactly. this is the basis for pixel perfect occlusion queries. Occlusion queries actually have GPU accelerated support, as long as you defer the readback for one or two frames it does not cause much lag. But this is very tricky to implement, and generally, is of no use. \$\endgroup\$ – v.oddou Oct 15 '14 at 1:58
2
\$\begingroup\$

You won't get away on this one with an easy answer. The raycast method is completely flawed. Its the same as calling the object "one pixel" wide and checking if this pixel is visible or not.
Unity uses a precalculated visibility matrix, composed with regular sectors of your world, and a quadratic ray cast test. Which has the same flaws but you don't need to implement anything, Unity has it built in. It takes a while to preprocess, you can even visualize the boxes getting computed and turning from red to white as it goes.

Visibility has been addresses throughout the years using:
- painting algorithm (draw from back to front)
- z buffer
- portals
- raycast (imperfect)
- occlusion queries
- crazy geometry based complex methods
like this one: http://research-srv.microsoft.com/en-us/um/people/johnsny/papers/vissort.pdf

Of course many of the aforemetnioned techniques does not let you know the visibility of one chosen object on the CPU side, but it depends of what you want to do with that information. Mostly its used as a render/not render flag so fed back to rendering. This is why the hardware occlusion queries can be kept on GPU side only and could perform OK in some situations.

The correct geometry based techniques usually resort to some conservative convex hull shape creation, then determine visibility against potential occluders anti-conservative hulls. This is not easy to do, takes a lot of CPU time and usually brings no benefit.

http://www.gamasutra.com/view/feature/131388/rendering_the_great_outdoors_fast_.php?print=1

http://bagira.iit.bme.hu/~szecsi/papers/occ.pdf

...

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.