首页 > 代码库 > 游戏AI之群组行为
游戏AI之群组行为
群组行为指的是多个对象组队同时进行的情况。每个boid需满足分离,队列,凝聚三个基本的规则。
分离:群组中的每个个体都与相邻的个体保持一定的距离。
队列:群组以相同的速度,向相同的方向移动。
凝聚:与群组的中心保持最小距离。
参见:http://www.red3d.com/cwr/boids/
结构:
控制器:即头鸟下有controller类来控制自身的移动。
个体成员:单独的个体,通过引用控制器的位置信息来产生群组跟随的效果。
群组中的个体:
1 using UnityEngine; 2 using System.Collections; 3 4 5 /// <summary> 6 /// 该类是对群体中的每个个体行为的约束,即单个的鸟 7 /// </summary> 8 public class UnityFlock : MonoBehaviour 9 { 10 11 //最小速度,转向速度,随机频率,随机力 12 public float minSpeed = 20.0f; 13 public float turnSpeed = 20.0f; 14 public float randomFreq = 20.0f; 15 public float randomForce = 20.0f; 16 17 //队列属性 :向心力,向心区间,吸引力 18 public float toOriginForce = 50.0f; 19 public float toOriginRange = 100.0f; 20 21 public float gravity = 2.0f; 22 23 //分离属性:规避力,规避半径 24 public float avoidanceForce = 20.0f; 25 public float avoidanceRadius = 50.0f; 26 27 //凝聚属性:追随速度,追随半径(相对于领导者即头鸟) 28 public float followVelocity = 4.0f; 29 public float followRadius = 40.0f; 30 31 32 //控制单个个体运动的属性:父对象即头鸟,速度,归一化速度,随机推力,父对象的推力。。。 33 private Transform origin; 34 private Vector3 velocity; 35 private Vector3 normalizedVelicity; 36 private Vector3 randomPush; 37 private Vector3 originPush; 38 private Transform[] objects; 39 private UnityFlock[] otherFlocks;//其他个体集合 40 private Transform transformCompont; 41 42 43 44 // Use this for initialization 45 void Start () 46 { 47 randomFreq = 1.0f/randomFreq;//获取随机变化的频率 48 //设置父节点为origin 49 origin = transform.parent; 50 51 transformCompont = transform; 52 53 //临时组件数组 54 Component[] tempFlocks = null; 55 56 if (transform.parent) 57 { 58 tempFlocks = transform.parent.GetComponentsInChildren<UnityFlock>(); 59 } 60 61 objects=new Transform[tempFlocks.Length]; 62 otherFlocks=new UnityFlock[tempFlocks.Length]; 63 64 //将群体的位置信息和群体加载到数组 65 for (int i = 0; i < tempFlocks.Length; i++) 66 { 67 objects[i] = tempFlocks[i].transform; 68 otherFlocks[i] = (UnityFlock)tempFlocks[i]; 69 } 70 71 transform.parent = null; 72 73 StartCoroutine(UpdateRandom()); 74 } 75 76 //基于randomFreq的频率来更新randompush的频率 77 IEnumerator UpdateRandom() 78 { 79 while (true) 80 { 81 randomPush = Random.insideUnitSphere*randomForce;//Random.insideUnitSphere随机返回单位球体类一点坐标,配合随机力度来跟新randomPush 82 yield return new WaitForSeconds(randomFreq+Random.Range(-randomFreq/2,randomFreq/2));//依据随机频率在一定时间分为类变换randomPush 83 } 84 } 85 86 // Update is called once per frame 87 void Update () 88 { 89 float speed = velocity.magnitude; 90 Vector3 avgVelocity = Vector3.zero; 91 Vector3 avgPosition = Vector3.zero; 92 float count = 0; 93 float f = 0.0f; 94 float d = 0.0f; 95 Vector3 myPosition = transformCompont.position; 96 Vector3 forceV; 97 Vector3 toAvg; 98 Vector3 wantedVel; 99 100 for (int i = 0; i < objects.Length; i++)101 {102 Transform transform = objects[i];103 if (transform != transformCompont)104 {105 Vector3 otherPositon = transform.position;106 107 //平均位置来计算聚合108 avgPosition += otherPositon;109 count++;110 111 //从其他群体到这个的向量112 forceV = myPosition - otherPositon;113 114 //上面向量的长度115 d = forceV.magnitude;116 117 //如果向量长度比规避半径小的话,则加大推力118 if (d < followRadius)119 {120 //如果当前的向量长度小于规定的逃离半径的话,则基于 逃离半径计算对象的速度121 if (d > 0)122 {123 f = 1.0f - (d/avoidanceRadius);124 avgVelocity += (forceV / d) * f * avoidanceForce;125 //向量除以它的模得到自己的单位向量126 }127 128 }129 130 //保持与头儿的距离131 f = d/followRadius;132 UnityFlock otherSealgull = otherFlocks[i];133 134 //标准化otherSealgul的速度来获取移动的方向,接下来设置一个新的速度135 avgVelocity += otherSealgull.normalizedVelicity * f *followVelocity;136 137 }138 }139 140 if (count > 0)141 {142 //得到平均速度143 avgVelocity /= count;144 //获得平均位置与对象间的向量145 toAvg = (avgPosition/count) - myPosition;146 }147 else148 {149 toAvg = Vector3.zero;150 }151 152 //153 forceV = origin.position - myPosition;154 d = forceV.magnitude;155 f = d/toOriginRange;156 //157 if (d > 0)158 originPush = (forceV/d)*f*toOriginForce;159 if (speed < minSpeed && speed > 0)160 velocity = (velocity/speed)*minSpeed;161 162 wantedVel = velocity;163 164 //最终速度165 wantedVel -= wantedVel*Time.deltaTime;166 wantedVel += randomPush*Time.deltaTime;167 wantedVel += originPush*Time.deltaTime;168 wantedVel += avgVelocity*Time.deltaTime;169 wantedVel += toAvg.normalized*gravity*Time.deltaTime;170 171 //调整速度使之转向最终速度172 velocity = Vector3.RotateTowards(velocity, wantedVel,turnSpeed*Time.deltaTime, 100.00f);173 174 transformCompont.rotation = Quaternion.LookRotation(velocity);175 176 //移动对象177 transformCompont.Translate(velocity*Time.deltaTime,Space.World);178 179 //跟新标准化向量的引用180 normalizedVelicity = velocity.normalized;181 }182 183 184 185 }
群组控制器(头鸟):
1 using UnityEngine; 2 using System.Collections; 3 4 /// <summary> 5 /// 头鸟决定飞行的整体方向,在unityflock中被origin引用 6 /// </summary> 7 public class UnityFlockController : MonoBehaviour 8 { 9 10 public Vector3 offset;//偏移11 public Vector3 bound;//范围12 public float speed = 100.0f;13 14 private Vector3 initialPosition;15 private Vector3 nextMovementPoint;16 17 //18 19 // Use this for initialization20 void Start ()21 {22 initialPosition = transform.position;23 CalculateNextMovementPoint();24 }25 26 // Update is called once per frame27 void Update () {28 transform.Translate(Vector3.forward*speed*Time.deltaTime);29 transform.rotation=Quaternion.Slerp(transform.rotation,Quaternion.LookRotation(nextMovementPoint-transform.position),1.0f*Time.deltaTime );//调整飞行角度30 31 if(Vector3.Distance(nextMovementPoint,transform.position)<=10.0f)32 {33 CalculateNextMovementPoint();34 }35 36 }37 38 void CalculateNextMovementPoint()39 {40 float posx = Random.Range(initialPosition.x - bound.x, initialPosition.x + bound.x);41 float posy = Random.Range(initialPosition.y - bound.y, initialPosition.y + bound.y);42 float posz = Random.Range(initialPosition.z - bound.z, initialPosition.z + bound.z);43 44 nextMovementPoint = initialPosition + new Vector3(posx, posy, posz);45 }46 }
效果:
游戏AI之群组行为
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。