前言:关于敌人判断在游戏中非常常见,有个插件BehaviourTree里面 有各Seeker ,实现算法 类似是下面的第二种。
下面介绍下 两种 算法,其原理 大致都一致;
算法1: 通过视距,视野角度 确定 敌人是否在视野中;
灵魂画师 上线了
解释:
在视野中要满足
1. 视距满足
2. 敌人和前方的夹角 要小于最大视野的一半; 一半是因为 敌人可能在玩家的左边,或者右边;
敌人和玩家的夹角 可以用Vector3.Angle 求得,玩家向前的方向是已知的, 玩家到敌人的方向 也是已知的,因此很容易求得。
视距就是玩家与敌人的距离。
public bool isFieldOfView(float fieldOfViewDistance, float fieldOfViewAngle, Transform Targer)
{
float dis = Vector3.Distance(transform.position, Targer.position);//求得距离
float angle = Vector3.Angle(transform.forward, Targer.position-transform.position );//求得夹角
if (dis < fieldOfViewDistance && angle < fieldOfViewAngle * 0.5)
{
return true;
}
return false;
}
第二种方式:
使用点积 来求得Cos 角度, 前提是必须在 以玩家视距为圆心 , 在圆内.实际上就是 不超过视距;
另一种方式是使用 点积;
解释
具体算法 是 取得 cos的角度, 度数转弧度*角度*二分之一
以自身坐标 为圆弧的中心,,取得从自身到 目标的方向。
单位向量点乘的结果 是它们的cos值,
cos在0~180° 上 为单调减,
函数图像
点乘公式
bool CheckPosition(Vector3 targetPos,float angle,float radius)
{
bool isCheck = false;
var cosAngle = Mathf.Cos(Mathf.Deg2Rad * angle * 0.5f); //以一位单位,取得Cos角度
Vector3 circleCenter = transform.position;
Vector3 disV = targetPos - circleCenter;//从圆心到目标的方向
float dis2 = disV.sqrMagnitude; // 得到 长度平方和
if (dis2<radius*radius) // 视距内
{
disV.y = 0.0f;
disV = disV.normalized; //向量除以它的长度 向量归一化 对向量
//开平方 得到向量长度
//归一化后,即是 单位向量了。
//用当前物体 向前方向,和从圆心到目标的单位方向 做 点积;
float cos = Vector3.Dot(transform.forward, disV);//求点积
//这样的结果就得到了cos角度*1
if (cos-cosAngle>=0)
{
return true; //在视野内
}
}
return false;
}