1.RayCast

只使用射线检测的好处是简单易用,但仅适用于 2D 或者对高度没有要求的俯视角游戏,很多场景并不适用
企业微信截图_16177910037760.png

2.角度判断 + RayCast

判断看向目标的向量与自身正前方向量的角度,若小于设定的角度,再向目标打出射线,若命中,则说明目标与自身之间没有阻碍,且角度,距离都正确

企业微信截图_16177910345094.png

可以适用于 3D 场景,但问题在于必须指定目标,并且单一射线目标不适于所有场景

3.Sphere Collider + RayCast + 角度判断

当有碰撞体进入时进行角度判断,再进行射线检测,相较于2方法,无需指定目标
企业微信截图_16177918366225.png

4.视锥检测

方法一  AABB包围盒

使用 TestPlanesAABB(Plane[] planes, Bounds bounds) 方法

使用 GeometryUtility.CalculateFrustumPlanes 方法从 Camera 组件上获取到视锥体的六个 Plane

这个方法有两个弊端,一是必须挂载 Camera 组件来使用,二是必须指定两个 AABB 盒才能进行判断,不适合使用

方法二 视锥形碰撞体

根据 Fov、near、far 等信息计算视锥顶点与三角面信息,手动绘制 Mesh,传入 MeshFilter,再由 MeshCollider 转化为碰撞体

顶点计算逻辑:Mathf.Tan(fov / 2 * Mathf.Deg2Rad);

使用起来与普通的碰撞体一样

5.扇形遮挡剔除

向指定角度打出若干射线,根据射线检测是否碰撞,若碰撞则返回碰撞点位置,没有碰撞则返回正常位置,根据位置信息绘制平面,实现剔除效果

缺点:不必要的 RayCast 太多,造成性能浪费

优化版:https://www.redblobgames.com/articles/visibility/

只向更近的物体顶点打出射线

企业微信截图_16177919858134.png

其他游戏视觉检测设计

《THE LAST OF US》 中的视线检测

早期沿用了神海的简单的锥体和射线来检测阻挡,但这样会导致贴AI的玩家不会被AI发现,而站在远处却会被敌人发现。

企业微信截图_16177920292171.png

修改了视锥,如图,使近距离的可视范围较大,并且让可视角度大小随距离延长逐渐变小。

企业微信截图_16177920365085.png

企业微信截图_16177920746924.png

视觉检测方式

AI会对视觉范围内的玩家做射线检测(阻挡检测),起初检测乔尔身体的每个关节,每个关节都有各自的权重,当检测到的权重之和达到阈值,就会认为乔尔被看到了。

但是由于计算太复杂,玩家无法预测哪些掩体是安全的。

在经过一些尝试之后,顽皮狗最终决定只用一个点来做检测,这个点会根据敌人的状态而变化。
当玩家没被发现,也就是处在潜行状态的时候,AI只检测乔尔胸部中心点的位置,而当玩家和AI处于战斗状态的时候,AI就检测玩家的头顶。(如下图所示)
企业微信截图_16177920993025.png

全境封锁的视觉检测

企业微信截图_16177921665408.png

其中有三个颜色的区域用作视觉刺激

黄:该区域的玩家将会被缓慢发现

橙:该区域的玩家将会被迅速发现

为了防止玩家跑到 AI 身后,设置了一圈红色区域

红:该区域的玩家会被立刻发现