Detect if object is visible on camera

I have a some cameras that are build up like security cameras and they should detect if a object is visible on screen.

To do that I want to send out some raycasts whenever I open my camera to see if there is a gameobject with a specific tag.
And if there is an entirely different way to approach this (with not using raycasts) then please tell me how.

I can’t just use renderer.isVisible and void OnBecameVisible because they are both not working for some reason.

I also wasn’t able to find a good video online about this topic, because they all just show how to shoot a raycast in front of you in a straight line and this would not work if the gameobject is in the corner of the camera.

Maybe I’m missing something here, but I would really appreciate if you could tell me if its even possible to shoot raycasts and like this and if yes if you could recommend a good tutorial on how to do that.

Thanks in advance.

1 Like

I can think of a few ways.

  1. shoot out a bunch of rays towards a grid of points in front of the camera. So first, create a grid of vector3 points, then cast a ray in the direction of each point.
  2. You can use an actual camera, then use the frustum to check overlaps
  3. Create a mesh in the shape of a cone in a 3D software (blender) then use it as a trigger collider to detect objects.
  4. Create a procedural mesh then use that as trigger collider.

If you go to this asset (Sensor Toolkit), they have documented exactly the methods they have used.
Sebastian Lague has a tutorial about sensors too, So you can apply this method in a 3D space once you understand how it’s done.

1 Like

The first thing to do is this:

Vector3 vpPos = Camera.main.WorldtoViewportPoint(targetTransform.position);
if (vpPos.x >= 0f && vpPos.x <= 1f && vpPos.y >= 0f && vpPos.y <= 1f && vpPos.z > 0f) {

The “viewport” is a description of screen space where (0,0) is the bottom left and (1,1) is the top right, while Z is the distance in front of the camera (so the .z > 0f part is checking to make sure it’s in front of the camera). So you convert the target object’s position to this space, and you can see if its center is within the screen.

You could do a Raycast in the direction of this point to make sure it’s not obscured by other objects:

Vector3 direction = targetTransform.position - Camera.main.transform.position;
if (Physics.Raycast(targetTransform.position, direction, out var raycastHit)) { // I forget actual racyast syntax/parameter order, check docs if this doesn't work
if (raycastHit.gameObject.transform != targetTransform) {
4 Likes

Thanks to both of you this was exactly what I needed.

I now have a basic working code. However I think how I did this is a really bad way of handling it, because its a lot of messy code and gameobjects. (TriggerEnter and TriggerExit with a lot of gameobjects and bools)

So I would like to use your code as a base, but I have a few questions.
In your first Script you have created a a view port. And you said that I can check if a target is on the camera.
How does this code work?
Do I have to place this code inside of my camera script and run it every time I change the camera?

And how can I check if the target is inside of this range like you said?

And thanks again man you both helped me alot.

You say I’ve “created a view port”, which is not a correct way of thinking about it. “the viewport” isn’t an object, it’s just a mathematical idea, representing the on-screen viewing space of the camera where points within the screen are within (0,0) and (1,1). So converting the world position to viewport space just makes the position a more convenient Vector3 to work with for our purposes, because (0,0) and (1,1) in that particular mathematical space is actually meaningful for us in a way that whatever the world position is, is not meaningful.

This code as written doesn’t depend on being attached to any particular object. Camera.main is a Unity convenience feature that finds a Camera with the MainCamera tag (which the default-created Camera object in the sample scene has). If you want to use a camera besides that one, you’ll need to assign that Camera as a reference on a public variable and use that. (The same applies to the targetTransform object I used in that script)

Does that help?

1 Like

Thanks man, that makes sense now.
Have a nice day. I’m now going to try to implement this.

Nice, ty