通过模拟鱼群或是雁群的群聚AI算法主要的有三种行为分别是分散,对齐,凝聚
即当鱼群之间距离靠的过近时它们会主动散开,当距离过远时它们又会往一起凝聚,其实散开和凝聚更多的都是左右两侧的力,但是如果还要整齐的向前行动,还需要一个对齐的力,这个力一般是指向行进方向上的,即周围个体的平均速度方向
下面基于Unity,提供一个概括实现思路
分散:每个单位行动时,要避免撞上其临近单位。
//1.首先要获得周围的鱼个体
//通过如下方法获得检测半径内的鱼,也就是附近的鱼(注意去除掉自己)
Collider[] colliders = Physics.OverlapSphere(transfrom.position,检测半径)
//得到得到去除自己后的ecm_colliders
#2计算出分离的力
#通过遍历附近的鱼与当前位置的方向计算出相互间排斥力的大小(每隔一段时间调用)
foreach(var c in ecm_colliders)
{
Vector3 dir = transform.position - c.transform.position;
//由于相互之间是排斥力,所以向量长度dir.magnitude越长,该方向上的力越小,反之亦然
//注意:repulsionForceALL 是外部定义的,计算附近鱼群给当前目标的合力
repulsionForceALL += dir.normalized / dir.magnitude;
}
//repulsionForceALL仅仅计算的是分离的力,总的力的大小,包括分离聚集和对齐的力为allForce
allForce += repulsionForceALL;
//得到附近给的力的合力之后,则可以在FixedUpdate中求出加速度
void FixedUpdate()
{
//根据牛二定律计算出加速度 和 当前速度包含方向
velocity += (allForce / m) * Time.fixedDeltaTime;
//将鱼的朝向转向速度的方向
transfrom.rotation = Quaternion.Slerp(transfrom.rotation,transform.LookAt(velocity),Time.fixedDeltaTime);
}
对齐:每个单位行动时,都要把自己对齐在其临近单位的平均方向上。
//大致同上,这里仅仅讲诉如何获取对齐的力
//这里ecm_colliders2不等于上面的ecm_colliders不同,因为它们的检测半径范围不一样
foreach(var c in ecm_colliders2)
{
//对齐的力实际上就应该等于附近每个鱼当前的方向,取所有方向总的朝向
allDir += c.transform.forward;
}
//将目标方向减去当前方向,得到使当前个体向周围方向对齐的力
allForce += allDir.normalized - transform.forward; //后面在fixedUpdate中同理调用
凝聚:每个单位都往其临近单位的平均位置行动。
N个点的中心坐标(x,y) = ( (x1+x2+x3+...+xN)/N , (y1+y2+y3+...+yN)/N )
//大致同上,这里仅仅讲诉如何获取聚集的力
//这里ecm_colliders等同于上面分散的ecm_colliders
foreach(var c in ecm_colliders)
{
//聚集的力实际上就应该是先计算周围所有点的中心,然后将当前物体向中心靠近
centerPosition += c.transform.position;
}
//得到中心的位置
centerPosition /= ecm_colliders.Length;
//中心位置减去当前的位置,得到朝向中心位置的方向,直接将其当作聚集的作用力
allForce += centerPosition - tranform.position;
网友评论