Search code examples
c#unity-game-enginescriptingcamerafrustum

How to detect all GameObjects within the Camera FOV? Unity3D


I would like to detect all gameobjects tagged by "Wall_[0-24]", which are within the camera FOV. I already tried Raycasting, but as it is only one ray, it doesn't catch multiple objects at the same time. I tried this one:

void Update() {
    GameObject walls = GameObject.FindGameObjectWithTag ("Wall");
    Renderer[] renders = walls.GetComponentsInChildren<Renderer> ();

    for (int i = 1; i < renders.Length; i++) {
        if (walls.GetComponentInChildren<Renderer> ().isVisible) {
            Debug.Log (renders[i] + " is detected!");
        } else {
            Debug.Log ("Nothing's detecetd!");
        }
    }
}

All I get is every wall again and again - doesn't really depend on the camera's position. As my camera follows a certain path, the visible walls should change. In the image the green part is visible and the red one not anymore (because the camera already passed them). explaining what should be output as a visible wall

So how could I realize the output of all seen walls by this specific camera?

Thank you for any help!


Solution

  • Using Draco18s' answer, below is how to implement what he said.

    Create a new Script and name it CheckWalls and attach the below code

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    
    public class CheckWalls : MonoBehaviour
    {
        Renderer[] renderers;
    
        void Awake ()
        {
            GameObject walls = GameObject.FindGameObjectWithTag ("Wall");
            renderers = walls.GetComponentsInChildren<Renderer> ();
        }
    
        void Update() 
        {
            OutputVisibleRenderers(renderers);
        }
    
        void OutputVisibleRenderers (Renderer[] renderers)
        {
            foreach (var renderer in renderers)
            {
                // output only the visible renderers' name
                if (IsVisible(renderer)) 
                {
                    Debug.Log (renderer.name + " is detected!");    
                }           
            }
    
            Debug.Log ("--------------------------------------------------");
        }
    
        private bool IsVisible(Renderer renderer) 
        {
            Plane[] planes = GeometryUtility.CalculateFrustumPlanes(Camera.main);
    
            if (GeometryUtility.TestPlanesAABB(planes , renderer.bounds))
                return true;
            else
                return false;
        }
    }