物体方位计算:
如跑酷游戏,主角在任意方向的曲线跑道上移动,通常会限定主角在水平方向只能在跑道中心左右一定范围内移动,避免主角移出跑道。这时就需要计算主角此时的位置是在跑道中心点的左侧还是右侧,以及距离中心点的距离,如果超过了左右两侧的临界点就不再向对应的方向移动。
离跑道中心的距离就可以这样计算:
float offsetX = Vector3.Dot(pathNormal, transform.position - pathPoint);
其中pathPoint是此时主角距离跑道路径最近的点,pathNormal是该点法线向量,这个法线向量就是指向跑道的右边,如果主角是始终朝向道路前方的,也可以使用主角的transform.right来代替。主角当前的位置减去离路径最近的点就得到了主角相对路径中心的方向,然后用主角的右向量点乘主角相对路径中心的方向就得到了此时玩家距离中心点的左右偏移距离,偏移值小于0表示在中心点左边,大于0表示在中心点右边。

上下坡/道路坡度计算:
CharacterController有个Slope Limit属性,即道路坡度不高于Slope Limit 时 CharacterController都能移动过去。也有很多人遇到斜坡过于陡峭时不让CharacterController继续移动的需求,此时CharacterController自带的功能就无法完成这一需求了。
根据CharacterController与地面碰撞的法线向量和当前路径点的朝向就可以计算出两个向量的夹角角度。
如图当在水平道路上移动时,碰撞法线与道路方向垂直,夹角为90度。
上坡时碰撞法线与道路方向的夹角大于90度。
下坡时碰撞法线与道路方向的夹角小于90度。
所以坡度就可以得出:
float slopeAngle = Vector3.Angle(hit.normal, transform.forward) - 90f;
private void OnControllerColliderHit(ControllerColliderHit hit)
{
if (hit.collider.CompareTag("Ground"))
{
float slopeAngle = Vector3.Angle(hit.normal, transform.forward) - 90f;
if (slopeAngle > 10)
{
Log.Info("上坡中...");
}else if (slopeAngle < -10)
{
Log.Info("下坡中...");
}
}
}