using System.Collections.Generic; using UnityEngine; public class CrowAI : MonoBehaviour { //当前速度 public float speed = 10; public Vector3 velocity = Vector3.forward; private Vector3 startVelocity;//初始化当前速度 public Transform target;//目标点 //总力 public Vector3 sumForce = Vector3.zero; //质量 public float m = 3; //分离的力 public float sparationDistance = 3; //分离的距离 public List<GameObject> sparationNeighbors = new List<GameObject>(); public float sparationWeight = 1; //权重 public Vector3 sparationForce = Vector3.zero; //队列的力 public float alignmentDistance = 4; public List<GameObject> alignmentNeighbors = new List<GameObject>(); public float alignmentWeight = 1; //权重 public Vector3 alignmentForce = Vector3.zero; //聚集的力 public float cohesionWeight = 3;//权重 public Vector3 cohesionForce = Vector3.zero; //间隔几秒检测一次 public float checkInterval = 0.2f; private Animation anim; public float animRandom = 2; void Start() { target = GameObject.Find("target").transform; startVelocity = velocity; //0 秒后调用 CalcForce() 方法,并且之后每隔 checkInterval 秒调用一次 CalcForce() 方法 InvokeRepeating("CalcForce", 0, checkInterval); anim = GetComponentInChildren<Animation>(); Invoke("Playanim", Random.Range(0, animRandom)); } void Playanim() { anim.Play(); } void CalcForce() { //计算之前先归零 sumForce = Vector3.zero; sparationForce = Vector3.zero; alignmentForce = Vector3.zero; cohesionForce = Vector3.zero; //先清空集合 sparationNeighbors.Clear(); Collider[] colliders = Physics.OverlapSphere(transform.position, sparationDistance); foreach (Collider c in colliders) { //判断该物体近的邻居 if (c!=null && c.gameObject!=this.gameObject) { sparationNeighbors.Add(c.gameObject); } } //1.计算分离的力 foreach (GameObject neighbor in sparationNeighbors) { Vector3 dir = transform.position - neighbor.transform.position; sparationForce += dir.normalized / dir.magnitude; } //如果附近有物体 if (sparationNeighbors.Count > 0) { //得到分离的力 sparationForce *= sparationWeight; //得到的力赋值给总力 sumForce += sparationForce; } //2.计算队列的力(整体一个前进的力) alignmentNeighbors.Clear(); colliders = Physics.OverlapSphere(transform.position, alignmentDistance); foreach (Collider c in colliders) { if (c!=null &&c.gameObject !=this.gameObject) { alignmentNeighbors.Add(c.gameObject); } } //计算邻居的平均朝向 Vector3 avgDir = Vector3.zero; //朝向的总和 foreach (GameObject n in alignmentNeighbors) { avgDir += n.transform.forward; } if (alignmentNeighbors.Count >0) { //得到平均数 avgDir /= alignmentNeighbors.Count; //得到相对方向 alignmentForce = avgDir = transform.forward; alignmentForce *= alignmentWeight; //得到的力赋值给总力 sumForce += alignmentForce; } //3.聚集的力 if (alignmentNeighbors.Count > 0) { Vector3 center = Vector3.zero; foreach (GameObject n in alignmentNeighbors) { center += n.transform.position; } center /= alignmentNeighbors.Count; Vector3 dirToCenter = center - transform.position; cohesionForce += dirToCenter.normalized * velocity.magnitude; cohesionForce *= cohesionWeight; sumForce += cohesionForce; } //4.保持恒定飞行速度的力 Vector3 enginForce = velocity.normalized * startVelocity.magnitude; sumForce += enginForce * 0.1f; //4.保持恒定目标飞行的效果 Vector3 targetDir = target.position - transform.position; sumForce += (targetDir.normalized - transform.forward)*speed; } void Update () { //加速度(根据牛顿第二定律) Vector3 a = sumForce / m; //计算出速度 velocity += a * Time.deltaTime; //物体运行 transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(velocity), Time.deltaTime*3); transform.Translate(transform.forward * Time.deltaTime * velocity .magnitude, Space.World); } }