简单的鱼群算法实现

鱼群算法根据鱼类的活动特点, 提出了一种基于动物行为的自治体寻优模式

鱼的聚群行为: 鱼在游动过程中会自然地聚集成群, 这也是为了保证群体的生存和躲避危害而形成的
一种生活习性 鱼群的形成也是一种突现的生动示例, Reyno lds 认为鸟类和鱼类的群集的形成并不需要
一个领头者, 只需要每只鸟或每条鱼遵循一些局部的相互作用规则即可, 然后群集现象作为整体模式从个
体的局部的相互作用中突现出来 Reyno lds 所采用的规则有三条: 1) 分隔规则: 尽量避免与临近伙伴过于
拥挤; 2) 对准规则: 尽量与临近伙伴的平均方向一致; 3) 内聚规则: 尽量朝临近伙伴的中心移动


我使用了其中1,2 条规则简单实现了下坦克分队移动的模拟
逻辑如下
1 监测自己与目标的距离和方向
2 监测周围单位的距离和移动方向
3 两个方向相加获得相量方向进行移动

工程下载(unity3d package)
http://pan.baidu.com/s/1F17yQ

简单的鱼群算法实现_第1张图片

简单的鱼群算法实现_第2张图片

简单的鱼群算法实现_第3张图片

代码如下

组:

 

 

public class TankGroup : MonoBehaviour {

         private static List tankGroups;//所有组

        

         public LayerMask mask;//成员层

         public int groupID=0;//id

         public float keepDistance=10, keepWeight=1;//成员保持距离和保持距离权重

         public float targetCloseDistance=20,targetWeight=1.25f, moveWeight=0.8f;//距离目标距离,距离目标权重和成员移动权重

}

坦克成员

 

 

public class TankBehaviour : MonoBehaviour {

         private const float minMoveCheck=0.2f;

        

         public int groupId=0;//组 id

         public float moveSpeed=5, rotateSpeed=20;//移动旋转速度

        

         public Vector3 position{

                   get{return transform.position;}

         }

        

         public Vector3 movement{

                   get{returnmyMovement;}

         }

        

         private Vector3 myMovement=Vector3.zero;

         private TankGroup myGroup;

         private float tgtSpeed=0, speed=0, currentSpeed;

        

         public void SetGroup(int index){

                   myGroup=TankGroup.GetTankGroup(index);

         }

        

         // Use this for initialization

         void Start () {

                   SetGroup(groupId);

         }

        

         // Update is called once per frame

         void Update () {

                   Vector3 displacement=myGroup.targetPosition-position;//获取目标距离

                   Vector3 direction=displacement.normalized*myGroup.targetWeight;//方向*权重

                  

                   if(displacement.magnitude//重新计算目的地距离权重

                           direction*=displacement.magnitude/myGroup.targetCloseDistance;

                  

                   direction+=GetGroupMovement();//获取周围组的移动

                  

                   if((myGroup.targetPosition-position).magnitude//计算移动速度

                            tgtSpeed=0;

                   else

                            tgtSpeed=moveSpeed;

                  

                   speed=Mathf.Lerp(speed,tgtSpeed,2*Time.deltaTime);

                  

                   Drive(direction, speed);//移动

         }

        

         private Vector3 GetGroupMovement(){

                   Collider[] c=Physics.OverlapSphere(position,myGroup.keepDistance,myGroup.mask);//获取周围成员

                   Vector3 dis,v1=Vector3.zero, v2=Vector3.zero;

                   for(int i=0; i

                            TankBehaviour otherTank=c[i].GetComponent();

                            dis=position-otherTank.position;//距离

                            v1+=dis.normalized*(1-dis.magnitude/myGroup.keepDistance);//查看与周围单位的距离

                            v2+=otherTank.movement;//查看周围单位移动方向

                           

                            Debug.DrawLine(position, otherTank.position, Color.yellow);

                   }

                  

                   return v1.normalized*myGroup.keepWeight+v2.normalized*myGroup.moveWeight;//添加权重因素

         }

        

         private void Drive(Vector3 direction, float spd){

                   Vector3 finialDirection=direction.normalized;

                  float finialSpeed=spd, finialRotate=0;

                   floatrotateDir=Vector3.Dot(finialDirection,transform.right);

                   floatforwardDir=Vector3.Dot(finialDirection,transform.forward);

                  

                   if(forwardDir<0)

                            rotateDir=Mathf.Sign(rotateDir);

                           

                   if(forwardDir<-0.2f)

                            finialSpeed=Mathf.Lerp(currentSpeed,-spd*8,4*Time.deltaTime);

                  

                   if(forwardDir<0.98f)//防抖

                            finialRotate=Mathf.Clamp(rotateDir*180,-rotateSpeed, rotateSpeed);

                  

                   finialSpeed*=Mathf.Clamp01(direction.magnitude);

                   finialSpeed*=Mathf.Clamp01(1-Mathf.Abs(rotateDir)*0.8f);

                  

                   transform.Translate(Vector3.forward*finialSpeed*Time.deltaTime);

                   transform.Rotate(Vector3.up*finialRotate*Time.deltaTime);

                  

                   currentSpeed=finialSpeed;

                   myMovement=direction*finialSpeed;

         }

        

}

你可能感兴趣的:(Unity3D)