1.RayCast
只使用射线检测的好处是简单易用,但仅适用于 2D 或者对高度没有要求的俯视角游戏,很多场景并不适用
2.角度判断 + RayCast
判断看向目标的向量与自身正前方向量的角度,若小于设定的角度,再向目标打出射线,若命中,则说明目标与自身之间没有阻碍,且角度,距离都正确
可以适用于 3D 场景,但问题在于必须指定目标,并且单一射线目标不适于所有场景
3.Sphere Collider + RayCast + 角度判断
当有碰撞体进入时进行角度判断,再进行射线检测,相较于2方法,无需指定目标
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/
只向更近的物体顶点打出射线
其他游戏视觉检测设计
《THE LAST OF US》 中的视线检测
早期沿用了神海的简单的锥体和射线来检测阻挡,但这样会导致贴AI的玩家不会被AI发现,而站在远处却会被敌人发现。
修改了视锥,如图,使近距离的可视范围较大,并且让可视角度大小随距离延长逐渐变小。
视觉检测方式
AI会对视觉范围内的玩家做射线检测(阻挡检测),起初检测乔尔身体的每个关节,每个关节都有各自的权重,当检测到的权重之和达到阈值,就会认为乔尔被看到了。
但是由于计算太复杂,玩家无法预测哪些掩体是安全的。
在经过一些尝试之后,顽皮狗最终决定只用一个点来做检测,这个点会根据敌人的状态而变化。
当玩家没被发现,也就是处在潜行状态的时候,AI只检测乔尔胸部中心点的位置,而当玩家和AI处于战斗状态的时候,AI就检测玩家的头顶。(如下图所示)
全境封锁的视觉检测
其中有三个颜色的区域用作视觉刺激
黄:该区域的玩家将会被缓慢发现
橙:该区域的玩家将会被迅速发现
为了防止玩家跑到 AI 身后,设置了一圈红色区域
红:该区域的玩家会被立刻发现