【问题标题】:How to detect all GameObjects within the Camera FOV? Unity3D如何检测相机 FOV 内的所有游戏对象? Unity3D
【发布时间】:2017-12-14 17:04:34
【问题描述】:

我想检测相机 FOV 内所有标记为“Wall_[0-24]”的游戏对象。我已经尝试过 Raycasting,但由于它只有一条射线,它不会同时捕获多个对象。 我试过这个:

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!");
        }
    }
}

我得到的只是一遍又一遍的每一面墙 - 并不真正取决于相机的位置。当我的相机沿着某个路径移动时,可见的墙壁应该会发生变化。在图像中,绿色部分可见,而红色部分不再可见(因为相机已经通过了它们)。

那么我怎样才能通过这个特定的相机实现所有看到的墙壁的输出

感谢您的帮助!

【问题讨论】:

  • 嗨,我想你应该问一个带问题的问题。也许这会对您遇到的问题以及您正在尝试做的事情有所了解。
  • @Programmer 但我已经这样做了?

标签: c# unity3d scripting camera frustum


【解决方案1】:

使用 Draco18s 的answer,下面是如何实现他所说的。

创建一个新脚本并将其命名为 CheckWalls 并附上以下代码

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;
    }
}

【讨论】:

  • 我修改了你的回答以引用 Draco 的回答,因为这正是他在回答中所说的,只是他没有在回答中包含完整的代码。
【解决方案2】:

第 1 步:Calculate the camera's frustum planes

第 2 步:Test each wall's collider against them,该页面上的示例脚本几乎包含您需要的一切。

如果对象在平面定义的体积内,那么它对相机可见(TestPlanesAABB(...) 返回 true),否则不可见。

如果您想知道某个对象是否可以从“摄像头”(即不是摄像头组件,而是一个充当安全摄像头但不进行任何实际渲染的对象)可见,则可以计算平面从任意点 (Vector3)、视图方向 (Vector3) 和视场(比率,作为浮点数)。我手头没有我写的代码,但如果需要的话可以拿来。

【讨论】:

  • 实际上,渲染相机应该可以看到(或不看到)对象。
  • @Viktoria 那么获得截锥体飞机很容易。请参阅第 1 步。
  • @Viktoria 所以,有两件事。 1) All I get is more than 100 times all walls again and again 是什么意思?以及 2) 我的回答如何解决您的问题
【解决方案3】:

这里的诀窍是您是要检测该游戏对象的第一个可见部分,还是要从对象的中心“检测”它。

如果您想对可见部分执行此操作,将脚本附加到这些对象以检查可见性可能会更简单。

如果您可以在中心可见后“检测”它,您可以通过相机进行检测。

不管怎样,我要做的第一件事就是使用 GameObject。 FindGameObjectsWithTag。 FindGameObjectsWithTag

然后,检查每个 Renderer.isVisible。 Renderer is Visible

在检查渲染器之前,您可以通过检查对象是否在相机后面来进一步优化这一点,因为这是一个更昂贵的操作。
Is that transform behind me?

如果这些都不能解决您的问题,请告诉我们更多关于您最终希望实现的目标。

编辑:根据您的新编辑,我会说您需要改用 Raycast All,

RaycastAll

【讨论】:

  • 我编辑了我的问题,也许现在更清楚了。
猜你喜欢
  • 2014-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-31
  • 2014-08-27
  • 1970-01-01
  • 2017-03-09
  • 1970-01-01
相关资源
最近更新 更多