x


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?

more ▼

asked Nov 19 '09 at 02:53 PM

unitynoob gravatar image

unitynoob
264 4 4 8

(comments are locked)
10|3000 characters needed characters left

3 answers: sort voted first

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

more ▼

answered Nov 19 '09 at 03:12 PM

duck gravatar image

duck ♦♦
41.4k 95 152 415

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?

Mar 10 '11 at 04:39 PM Gillissie

To make things easier for doing the frustum check - http://www.unifycommunity.com/wiki/index.php?title=IsVisibleFrom

Mar 15 '11 at 08:37 PM Mike 3

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.

Jun 17 '12 at 08:11 AM Bovine
(comments are locked)
10|3000 characters needed characters left

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.

more ▼

answered Nov 19 '09 at 03:20 PM

runevision gravatar image

runevision ♦♦
8.1k 29 46 112

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..

Dec 19 '11 at 11:28 PM Bovine

This answer is very important, expecially if you have to do such a calculation very often! With CalculateFrustumPlanes you createa 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 ?

Feb 01 '12 at 06:52 PM Fire-Dragon-DoL
(comments are locked)
10|3000 characters needed characters left

If the object has a renderer attached, then this should work:

Create a new class cameraSight and array of this class named seenByCameraList

class cameraSight {
    var cam : Camera;
    var sawMe : boolean;
    var seesMe : boolean;
};
var seenByCameraList: cameraSight[];

then initialize it in Start()

var tempCameraList:Camera[] = Camera.allCameras;
seenByCameraList = new cameraSight[tempCameraList.Length];
for (var i:int=0;i<seenByCameraList.Length;i++)
    {
    seenByCameraList[i]=new cameraSight();
    seenByCameraList[i].cam=tempCameraList[i];
    seenByCameraList[i].sawMe=false;
    seenByCameraList[i].seesMe=false;
    }

Assuming that camera count will not be changed dynamicaly, in Update() just clear flags to false;

for (i=0;i<seenByCameraList.Length;i++)
{
seenByCameraList[i].sawMe=seenByCameraList[i].seesMe;
seenByCameraList[i].seesMe=false;
}

If Unity whave to render this object, it will call OnWillRenderObject() , where we modify the flags for cameras, to which this object is visible

function OnWillRenderObject () {
for (var i:int=0;i<seenByCameraList.Length;i++)
    {
    if (seenByCameraList[i].cam==Camera.current) seenByCameraList[i].seesMe=true;
    }
}

And the final function which you call for testing visibility to particular camera

function isRendererVisibleByCamera(observerCamera:Camera){
for (var i:int=0;i<seenByCameraList.Length;i++)
{
if (seenByCameraList[i].camera==observerCamera) return seenByCameraList[i].sawMe;
}
}

To avoid clearing of flag, there is sawMe flag which copies a value of seesMe from previous frame. So information is one frame delayed.

more ▼

answered Jan 14 at 07:05 PM

mmax gravatar image

mmax
1 1

(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

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

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x3132
x155
x96
x19

asked: Nov 19 '09 at 02:53 PM

Seen: 24430 times

Last Updated: Jan 14 at 07:29 PM