问题
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).
So how could I realize the output of all seen walls by this specific camera?
Thank you for any help!
回答1:
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;
}
}
回答2:
Step 1: Calculate the camera's frustum planes.
Step 2: Test each wall's collider against them, the example script on that page has literally everything you need.
If the object is inside the volume defined by the planes, then its visible to the camera (and TestPlanesAABB(...)
returns true), otherwise it is not.
If you want to know if an object is visible from a "camera" (that is, not a camera component, but an object that acts like a security camera, but is not doing any actual rendering) the planes can be computed from an arbitrary point (Vector3), view direction (Vector3), and field of view (a ratio, as a float). I don't have the code I wrote on hand, but can fetch it if needed.
回答3:
The trick here is whether you want to detect the first visible part of that game object, or if you want to 'detect' it from the object's center.
If you want to do this with the visible part, it might be simpler to attach a script to those objects to check visibility.
If you are okay with "detecting" it once the center is visible, you can do it from the camera.
Either way, the first thing I'd do is use GameObject. FindGameObjectsWithTag. FindGameObjectsWithTag
Then, check Renderer.isVisible for each of them. Renderer is Visible
You could further optimize this by checking to see if the object is behind the camera or not, first, by its transform, before you check the renderer, since that's a more expensive operation.
Is that transform behind me?
And if those don't fix your problem, tell us more about what you ultimately hope to achieve.
Edit: based on your new edit, I'd say you need to use Raycast All instead,
RaycastAll
来源:https://stackoverflow.com/questions/45020915/how-to-detect-all-gameobjects-within-the-camera-fov-unity3d