碰撞查询
碰撞检测的另一任务是回答关于游戏世界中碰撞体积的假想问题(hypothetical question),例如物体从A点移动到B点是否会碰到什么障碍物,例如找出给定半径内所有敌人对象。这些操作被称为碰撞查询(collision query)。碰撞查询的尸体并不存在于碰撞实体,它完全不会影响世界中的其他物体。
最常用的查询类型是投射(cast)。
1.射线投射
最简单的投射是射线投射(ray cast)。射线投射实际上投射的是有向线段,有起点和终点(多数碰撞系统不支持无限长的光线)。投射线段如果与碰撞世界物体相交,可以传回最早接触点或者所有接触点的集合。
射线投射系统的线段通常以起点p0以及增量向量d描述,起点加上增量向量后就会得出终点p1。
- 此线段上任何点都可以在以下的参数方程中求得:
$p(t) = p_0 + td, t ∈[0, 1]$
- 接触点的数据结构可以表示为:
struct RaycastHit{
float t;//接触点的t值
uint colliderId;//击中的碰撞体ID
vec3 normal; //接触点法线
//...其他信息
}
射线投射的应用:
- 视线判断
- 武器系统
- AI系统
- 载具系统
- 其他…
2.形状投射
形状投射(shape cast)另一种对碰撞系统的常见查询,是查询一个凸形状可以沿一有向线段移动多远才会碰到其他物体。
- 投射凸形状时需要考虑的两种情况:
- 投射形状已插入或者接触到至少一个其他的碰撞体。
- 投射形状在起点没有与任何其他碰撞体相交。
- 形状投射传回的接触信息会比光线投射更复杂一些:
struct ShapeCastContact
{
float t;
uint colliderId;
vec3 contactPoint;
vec3 normal;
//...其他信息
}
形状投射的应用:
- 判断摄像机是否与游戏世界的物体碰撞。
- 角色移动时的离地检测。
3.Overlap
有时需要判断碰撞体是否位于游戏中某些特定体积内。例如获取一个半径范围内所有敌人列表。
Havok提供一种特别的碰撞体”Phantom”,Phantom和零距离形状投射的区别是Phantom是持续存在的,能利用时间一致性优化。
Cre:Unity中可以调用Physics.Overlap()
来获取范围内所有碰撞体。
4.其他查询
Havok支持最近点(closest point)查询,给定一个碰撞体,就能找出其他接近的碰撞体上的最近点集合。
(END)