检查游戏对象在当前相机上是否可见



我在堆栈溢出和互联网上搜索了一段时间,试图寻找这个问题的解决方案,每次我尝试使用OnBeameVisible((或OnBeameInvisible((或者TestPlanesABB来检查对象是否通过墙看不见,相机仍然可以通过实心墙看到对象。

此处的问题视频:https://youtu.be/3HiEugm6On8

正如你所看到的,如果我看着他,他就会停止移动,如果我转过身来,他就会";卸载";或";变得不可见";他走得更近了,但如果我转过一个拐角,仍然朝着他的方向看,他就停止了移动,好像我能看到他一样,那里没有墙,这就是我想要解决的

这是一个四处游荡的敌人,我希望他只有在我看不到他的情况下才能移动,我认为这会很简单,但遗憾的是,它似乎没有我认为的那么简单

我目前的代码是基本的:

public bool IsSeen = false;
public void OnBecameVisible()
{
Debug.Log("I can now see you");
IsSeen = true;
}
public void OnBecameInvisible()
{
Debug.Log("I can't see you");
IsSeen = false;
}

这适用于我希望通过墙壁检测/不检测的对象,我相信这会检查我选择的相机是否可以看到该对象。

有人知道我该如何解决/实现这个问题吗?

如前所述;"问题";Renderer.OnBecameVisible

请注意,当需要在场景中渲染对象时,该对象被视为可见。它可能不会被任何相机实际看到,但仍然需要为阴影进行渲染此外,在编辑器中运行时,场景视图摄影机也会导致调用此函数

所以它对你来说真的不可用。

有没有一种简单的方法可以对整个屏幕进行光线投射?

不幸的不是真的:/

使用GeometryUtility.CalculateFrustumPlanes可以稍微避免这种情况,以便获得相机截头体的四个平面。然后,您可以使用GeometryUtility.TestPlanesAABB检查对象是否真的在截锥体内

var cam = Camera.main;
var planes = GeometryUtility.CalculateFrustumPlanes(cam);
var objCollider =  GetComponent<Collider>();
if (GeometryUtility.TestPlanesAABB(planes, objCollider.bounds))
{
Debug.Log("I am inside the camera frustrum!");
}
else
{
Debug.Log("I am out of sight...");
}

然而,这仍然没有覆盖目标物体前面的任何其他物体,因此实际上覆盖了它

您需要准确定义可见的含义(例如,网格的任何部分?对象的中心是否足以测试?等等(。

例如,只测试对象的中心,可以使用类似的Physics.Linecast

if (GeometryUtility.TestPlanesAABB(planes, objCollider.bounds))
{
Debug.Log("I am inside the camera frustrum!");
if(Physics.LineCast(cam.transform.position, objCollider.GetComponentInChildren<Renderer>().bounds.center, out var hit)
{
if(hit.gameObject != objCollider.gameObject)
{
Debug.Log("..but something else is in the way..");
}
else
{
Debug.Log("Now you see me, muhaha!");
}
}
}

如果你想让它更精确,并且网格任何部分的轨迹都是可见的,那么它实际上会变得很棘手。您需要根据需要对边界框的多个关键点(例如,每个角、边的中心等(进行光线投射。

最新更新