如何检查一个游戏对象是不是可以看到另一个?

Posted

技术标签:

【中文标题】如何检查一个游戏对象是不是可以看到另一个?【英文标题】:How can I check if one game object can see another?如何检查一个游戏对象是否可以看到另一个? 【发布时间】:2010-09-17 06:08:42 【问题描述】:

我有一个对象,它面向特定方向,具有(例如)45 度视野和极限视野范围。我已经完成了所有初始检查(四叉树节点和距离),但现在我需要检查特定对象是否在该视锥内,(在这种情况下,如果我们能看到它,则决定只跟随该对象)。

除了为从Direction - (FieldOfView / 2)Direction + (FieldOfView / 2) 的每个度数投射一条射线(我现在正在这样做,这太可怕了),进行这种可见性检查的最佳方法是什么?

【问题讨论】:

【参考方案1】:

我曾在视频游戏行业工作过,我可以说像 arccos 这样的三角函数每帧都不太理想。相反,您预先计算锥角的余弦:

float cos_angle = cos(PI/4); // 45 degrees, for example

然后,您可以通过将每一帧与圆锥和 . 的点积进行比较来快速检查一个点是否落在该圆锥内。

vector test_point_vector = normalize(test_point_loc - cone_origin);
float dot_product = dot(normalized_cone_vector, text_point_vector);
bool inside_code = dot_product > cos_angle;

没有三角函数,只有一些乘法、除法和加法。大多数游戏引擎都为向量优化了 normalize() 函数。

这是因为这个等式有效:

A · B = |A| * |B| * cos(Θ)

如果对向量 (A -> An) 进行归一化,则方程会简化:

An · Bn = cos(Θ)

【讨论】:

谢谢。我喜欢限制每帧触发函数数量的想法。我一定会考虑试试这个(遗憾的是,只有在考试结束后)。 我喜欢这个答案。请注意,此解决方案只会进行“平截头体检查”,不会处理墙壁和其他物体的遮挡。【参考方案2】:

计算您的视图方向(理解为向量)与从您开始到对象结束的向量之间的角度。如果它属于 FieldOfView/2,您可以查看该对象。

那个角度是:

arccos(scalarProduct(viewDirection, (object - you)) / (norm(viewDirection)*norm(object - you))).

【讨论】:

谢谢,正是我想要的。根据我已有的,我认为这可能是实现这一目标的最简单方法。【参考方案3】:

获取查看器的航向矢量与查看器到目标的矢量之间的角度。如果该角度小于 (FieldOfView/2),则目标位于观察者的视野中。

如果您的向量是 2d 或 3d,则其工作方式相同。 (在 3D 中,如果你有一个视锥体而不是圆锥体,那么你需要将角度分成两个分量。)你只需要找到两个向量之间的角度。

如果要测试大于单个点的目标,则每个目标都需要多个点,例如边界框的角。如果从观察者到这些点的向量给出了视野内的一个角度,那么盒子的那个角是可见的。

【讨论】:

【参考方案4】:

如果您正在制作 3D 并且可以将查看范围定义为视锥体,那么您可以使用类似于 Frustrum Culling 技术的东西。

【讨论】:

【参考方案5】:

已经有了很好的答案,但我只是想给你一个 Wolfire 博客的链接,他们最近开始了一个代数系列,以“视野”方程为例。 Go read it,写得很好,很容易。

【讨论】:

以上是关于如何检查一个游戏对象是不是可以看到另一个?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 FluentAssertions 检查对象是不是从另一个类继承?

如何检查用户是不是可以看到视图[重复]

如何检查包含另一个对象数组的对象数组是不是具有属性

如何检查一个 sknode 是不是触及另一个

量角器 - 如何检查对象是不是包含在另一个对象中?

如何检查游戏对象是不是处于活动状态