Figuring out if an object is seen or not

Hello people!

Every weekend I start up a new little project to test concepts, try new techniques and most of all: to keep myself entertained. This weekend my project is named “An Experiment in Horror”, so I’m going for the creation of suspense and psychological fear. I feel the project had a good start since I wrote all my base ideas and plans during a stormy night.

Anyway, the main mechanic of this experiment is to know if an object has been seen or not. Pretty much all scripts will build on the base-class Sight. (That’s Sight as in “a sight worth seeing” not as in “you have excellent sight”). Since this class is so integral to the whole experience I want to get it right. Hence I’d like to see if anyone can come up with improvements or other suggestions on my plans! It might be worth mentioning that this will be done in first person view.

What I need input on is handling visual detection. At the moment my structure looks is divided into three steps.

Step 1: Major culling
This step should be as cheap as possible and remove as many objects as possible. It’s for getting rid of objects which obviously can not be seen. The thoughts I’ve had on it so far is:

  • Distance
    Each object compares it’s position to the player’s position: Vector3.Distance(transform.position, Player.position) < maxVisualRange

  • Occlusion
    Since I’m on Unity Pro I have access to the Occlusion Culling feature. In this approach I’d simply check if the renderer is enabled or not.

  • Sphere Overlapping
    I perform a Physics.OverlapSphere with origin from the player, all objects in it passes step 1.

Step 2: Directional culling
During this step I check if the object is in the direction the player is currently looking.

  • Dot
    So far the only approach I’ve come up with. Perform a Dot product on the camera’s forward vector and the normalized vector from the camera to the object. Should the result be above 0.7 the object passes.

Step 3: Final culling
If an object has reached this step it is worth a check with a bit heavier performance.

  • Raycast
    A ray is cast from the camera’s position to the object. If the ray hits the object, the object passes and has been seen. This approach will not be very accurate for large objects, but as of now I don’t think such large objects will be necessary.
  • Multiple Raycasts
    Several rays are cast from the camera to the object. The first ray is cast towards the center, should that one not succeed rays are cast towards the bounding-box corners of the object.

That’s my thoughts so far!
For step 1 I’m leaning towards the Occlusion approach. I might use Occlusion Culling whatever approach I choose so I might aswell take advantage of that.
Since I have no particular alternatives for step 2 as of yet, it seems Dot will be what I do there.
I believe a single ray should be enough for step 3, after all I want to make sure the player has actually seen the object. Which is not the same thing as “the player has at some point turned the camera so that the object was in view”.

Any and all input on the subject will be appreciated!
Thank you for taking the time to read this big piece of text!

No need to jump through such hoops.

First, the heavy processing you think is in your third step is actually in your first. Running Vector3.distance over every gameobject is going to eat a boatload of cpu cycles, as each call involves a square root.

If you want to cull objects by distance, simply use two cameras and have them cull objects by distance/layer for you.

In terms of your ‘sight’ calculations, just use the OnBecameVisible/Invisible callbacks and have the frustum culling take care of that for you. Add to an array, flip a bool, whatever you need to have done.

Ah, camera magic. Not something I have experimented alot with before. I shall definetly have a look at it!

Do you know if the OnBecomeVisible/Invisible functions take shadows into regard?
Edit: Nevermind, I found the answer with a few clicks.

Well. This will make things alot easier by the looks of it. Many thanks!