• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
66
Question by unitynoob · Nov 19, 2009 at 02:53 PM · cameraviewcheckfrustrum

How can I know if a gameObject is 'seen' by a particular camera?

How can I know if a gameObject is 'seen' by a particular camera?

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image vvkkumar06 · May 27, 2014 at 03:19 PM 0
Share

I think you can also use RayCast from camera to object to deter$$anonymous$$e it.

avatar image tanoshimi · May 27, 2014 at 07:19 PM 3
Share

@vvkkumar06 5 years too late and repeating what @duck said. But, other than that, useful comment...

11 Replies

· Add your reply
  • Sort: 
avatar image
124
Best Answer

Answer by duck · Nov 19, 2009 at 03:12 PM

There's a whole slew of ways to achieve this, depending on the precise functionality you need.

You can get events when an object is visible within a certain camera, and when it enters or leaves, using these functions:

OnWillRenderObject, Renderer.isVisible, Renderer.OnBecameVisible, and OnBecameInvisible

Or you can calculate whether an object's bounding box falls within the camera's view frustum, using these two functions:

GeometryUtility.CalculateFrustumPlanes GeometryUtility.TestPlanesAABB

If you've already determined that the object is within the camera's view frustum, you could cast a ray from the camera to the object in question, to see whether there are any objects blocking its view. Physics.Raycast

Comment
Add comment · Show 8 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Gillissie · Mar 10, 2011 at 04:39 PM 1
Share

Is it just me, or does the example for http://unity3d.com/support/documentation/ScriptReference/GeometryUtility.TestPlanesAABB.html only work for a static camera? It gets the frustum planes in the Start() method, so if the camera moves it will be inaccurate. Am I correct in thinking that?

avatar image Bovine · Jun 17, 2012 at 08:11 AM 2
Share

Irritatingly OnBecameInvisible happens for all cameras in the scene, including the editor camera. This is a bit rubbish tbh, because it means behaviour changes between editor and game and there's no coding around this. Being able to detect that an object is visible by a camera and then ceases to be visible by that same camera is very very useful, and it being visible by the editor camera is not something I need to know in game, but could be handled by this...

Ho hum, I'll have to do something computationally more expensive by the sounds of things :o(

EDIT: I thought OnBecameVisible() was called for each camera I think it is also called once, but it is relatively random as to which camera considers it visible, so Camera.current might be (irritatingly) the scene camera, or it might be a real in-game camera, but if both see it, it will only be called once.

avatar image indolence · Nov 26, 2014 at 09:25 PM 0
Share

@Gillissie (several years late): I got this to work just by moving that line into the Update method.

avatar image BrianLedsworthGSN · May 01, 2017 at 10:52 PM 0
Share

Note: The "GeometryUtility.TestPlanesAABB" seems to return true even if just a "portion" of the GO is visible. I would not use this if you want to ensure the entire GO is visible.

avatar image raphadko BrianLedsworthGSN · Jul 14, 2017 at 09:18 PM -1
Share

So, what would you use in this case?

avatar image MagicStyle · Nov 06, 2017 at 11:40 AM 0
Share

Renderer.isVisible does not exist

avatar image AidanHorton MagicStyle · Nov 06, 2017 at 11:52 AM 1
Share

On the object you are testing if it's visible or not, in the update, put the following:

 if (GetComponent<Renderer>().isVisible)
 {
     //Visible code here
 }
 else {
     //Not visible code here
 }

Please note that even if the object is out of view of the camera, it may still be classed as visible if the object needs to be rendered for shadows that it is casting that are still visible.

Show more comments
avatar image
64

Answer by runevision · Nov 19, 2009 at 03:20 PM

The answer given by Duck is the most accurate. If you can do with something less accurate, you can consider just checking if the position of the object is seen by the camera.

To find out if a point in the scene is seen by a camera, you can use Camera.WorldToViewportPoint to get that point in viewport space.

If both the x and y coordinate of the returned point is between 0 and 1 (and the z coordinate is positive), then the point is seen by the camera.

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bovine · Dec 19, 2011 at 11:28 PM 0
Share

I suppose doing this for the extents of the GO would be enough... I've been using something more event driven, but I'm not so sure about this now (Triggers with rigid-bodies attached). Perhaps raycasts betwee . n objects are fine or squared delta comparisons, moving to something related to one of the above solutions at a late date..

avatar image Fire-Dragon-DoL · Feb 01, 2012 at 06:52 PM 0
Share

This answer is very important, expecially if you have to do such a calculation very often! With CalculateFrustumPlanes you crea$$anonymous$$ new object on the heap (an Array), while with this you don't allocate anything new. For intensive usage, this should be the correct method. Just a question, Z coordinate positive you mean greater than 0 or greater or equal to 0 ?

avatar image VipHaLongPro · Apr 12, 2015 at 01:06 PM 0
Share

I did not test this but I've experienced a problem with the Camera.WorldToScreenPoint (some kind of similar to Camera.WorldToViewportPoint but returns absolute value). The problem is when the object is such as behind the camera, the returned value may still fall in (0,0) - (1,1). So basing on that won't help detect if the object is in the camera view.

avatar image Taylor-Libonati · Jul 02, 2015 at 06:19 PM 7
Share

This solution worked great for me. Just be sure to check the Z value as well.

Here is a script example. I am checking to see when the user has looked at something for over X seconds.

 public Transform targetPoint;
 public float holdGazeTimeInSeconds = 2;
 
 private float currentGazeTimeInSeconds = 0;

 void Update () {
     Vector3 screenPoint = playerHead.leftCamera.WorldToViewportPoint (targetPoint.position);
     if (screenPoint.z > 0 && screenPoint.x > 0 && screenPoint.x < 1 && screenPoint.y > 0 && screenPoint.y < 1) {
         currentGazeTimeInSeconds += Time.deltaTime;
         if(currentGazeTimeInSeconds >= holdGazeTimeInSeconds){
             currentGazeTimeInSeconds = 0;
             //DO STUFF
 
         }
     } else {
         currentGazeTimeInSeconds = 0;
     }
 }
avatar image josh_kuttler · Mar 09, 2019 at 10:36 AM 0
Share

Thank you, it's helped me and work very good.

Show more comments
avatar image
14

Answer by V-Jankaitis · Mar 20, 2015 at 04:58 PM

private bool I_Can_See(GameObject Object) {

      Plane[] planes = GeometryUtility.CalculateFrustumPlanes(Camera);


      if (GeometryUtility.TestPlanesAABB(planes , Object.collider.bounds))
          return true;
      else
          return false;
 }
Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image BrianLedsworthGSN · May 01, 2017 at 10:51 PM 0
Share

Note: This will return true even if just a "portion" of the GO is visible. I would not use this if you want to ensure the entire GO is visible.

avatar image Zebbi · Aug 06, 2019 at 06:55 PM 0
Share

This is perfect, I wanted to test if absolutely any part of the collider was visible and this worked perfectly thanks!

avatar image Gabi_RP · Nov 11, 2021 at 10:38 PM 0
Share

Just

  private bool ICanSee(GameObject object)
     {
         Plane[] planes = GeometryUtility.CalculateFrustumPlanes(Camera);
          return GeometryUtility.TestPlanesAABB(planes , Object.collider.bounds);
     }
avatar image unity_116E85ED89B8777DCD65 · May 21 at 01:21 PM 0
Share

Great example.

avatar image
7

Answer by tall-josh · Mar 22, 2017 at 10:13 AM

I spent a fair while looking into this, the suggestions from @duck where led me down the right path, but I ended up doing it in 3 steps. Note: I am checking objects with several LODs associated with them, so I'm using GetComponentInChildren(), as uposed to GetComponent()

1) Check if the object is in front of the screen: Convert the center point of the object (toCheck) from world coordinates, to screen relitave coordinates. In the screen relitave coordinate system the z axis represents distance infront (+) or behind (-) the screen

2) Check if the objcect is within the camera's field of view: I found a few ways to do this, but in the end I figured if i already have the point relitave to screen coordinates. If the x,y position in screen coordinates is outside the window size then it is obversly not in the camera's field of view.

3)Check if the object is being occluded by anything: This was a bit tricky and in the end I used Physics.Linecast(...) instead of Physics.Raycast(...) because I already had the origin and target of the line so I did not need to figure out angles if I used Linecast(...). I just cast the line and if the object it hit did not have the same name as the object I was aiming for (in my case a tree) then I knew something was in the way.

So all together it looks like this:

 private bool IsInView(GameObject origin, GameObject toCheck)
     {
         Vector3 pointOnScreen = cam.WorldToScreenPoint(toCheck.GetComponentInChildren<Renderer>().bounds.center);
 
         //Is in front
         if (pointOnScreen.z < 0)
         {
             Debug.Log("Behind: " + toCheck.name);
             return false;
         }
 
         //Is in FOV
         if ((pointOnScreen.x < 0) || (pointOnScreen.x > Screen.width) ||
                 (pointOnScreen.y < 0) || (pointOnScreen.y > Screen.height))
         {
             Debug.Log("OutOfBounds: " + toCheck.name);
             return false;
         }
 
         RaycastHit hit;
         Vector3 heading = toCheck.transform.position - origin.transform.position;
         Vector3 direction = heading.normalized;// / heading.magnitude;
         
         if (Physics.Linecast(cam.transform.position, toCheck.GetComponentInChildren<Renderer>().bounds.center, out hit))
         {
             if (hit.transform.name != toCheck.name)
             {
                 /* -->
                 Debug.DrawLine(cam.transform.position, toCheck.GetComponentInChildren<Renderer>().bounds.center, Color.red);
                 Debug.LogError(toCheck.name + " occluded by " + hit.transform.name);
                 */
                 Debug.Log(toCheck.name + " occluded by " + hit.transform.name);
                 return false;
             }
         }
         return true;
     }



Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image jackson_31 · Jul 08, 2017 at 11:32 PM 0
Share

This is awesome. Your solution works.

For me I am trying to check visibility of terrains from camera So I will just have to add more points other than just the center.

avatar image mangoj5187 · Jul 22, 2019 at 01:26 PM 0
Share

Hello quick question. Did you attach this script on the camera?

avatar image Hassan-Kanso · Jun 07, 2021 at 05:50 PM 0
Share

this should be the right answer, isVisible and Frustum do not deliver the describe request by OP.

avatar image
3

Answer by oPless_ · Mar 07, 2016 at 07:28 PM

Coming to the party late, but here's an alternative.

 bool IsTargetVisible(Camera c,GameObject go)
     {
         var planes = GeometryUtility.CalculateFrustumPlanes(c);
         var point = go.transform.position;
         foreach (var plane in planes)
         {
             if (plane.GetDistanceToPoint(point) < 0)
                 return false;
         }
         return true;
     }


GeometryUtility .TestPlanesAABB can throw exceptions, this is a more generic solution, which works for only the point case, solving for 'bounds' is left as an exercise for the reader :)

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
  • 1
  • 2
  • 3
  • ›

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

26 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Camera frustums + custom field of view 2 Answers

How to draw an outline of a camera view along a path ? 0 Answers

how can i moving from camera to other using a code? 1 Answer

Camera location to camera location animation 2 Answers

Mouse position in camera view area 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges