不使用群组行为
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Crow : MonoBehaviour
{
public float animRandom = 2f;
public float speed = 1;
public Transform target;
//public Vector3 velocity = Vector3.forward; //有target之后就不能使用了
//取消Play Automatically
private Animation animation;
private IEnumerator Start()
{
//因为是场景中的物体所以无法拖拽apply
target = GameObject.Find("Target").transform;
animation = GetComponentInChildren<Animation>();
yield return new WaitForSeconds(Random.Range(0, animRandom));
animation.Play();
}
void Update ()
{ //向前移动没有目标
//this.transform.Translate(velocity * Time.deltaTime, Space.World);
//有目标
transform.LookAt(target.position);
transform.Translate(Vector3.forward * Time.deltaTime * speed);
}
}
使用群组行为实现分离,队列,聚散
牛顿第二定律:速度V,加速度a,质量m;第二定律:F=ma,a=F/m;F为受到的力;所以在程序中a=F;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CrowNew : MonoBehaviour
{
private Vector3 startVelocity; //初始速度
private Vector3 velocity = Vector3.forward; //速度
private float m = 1; //质量
//添加一个向量 合力
private Vector3 sumForce = Vector3.zero;
//分离力
private Vector3 separationForce = Vector3.zero;
public float separationDistance = 3; //分离的距离,3米以内的乌鸦将分离
private List<GameObject> separationNeighbors = new List<GameObject>(); //存放得到的3米内的物体
public float separationWeight = 1; //分离力的权重
//队列的力
private Vector3 alignmentForce = Vector3.zero;
public float alignmentDistance = 6; //队列力的距离
private List<GameObject> alignmentNeighbors = new List<GameObject>();
public float alignmengWight = 1;
//聚集的力
private Vector3 cohesionForce = Vector3.zero;
public float cohesionWight = 1;
private float checkInterval = 0.2f; //检查时间间隔
private Animation ani;
private float animRandom = 2f;
#region 计算力的方法
private void CalcForce()
{
sumForce = Vector3.zero;
separationForce = Vector3.zero;
alignmentForce = Vector3.zero;
cohesionForce = Vector3.zero;
#region 分离力
separationNeighbors.Clear();
//计算3米内有什么物体
Collider[] colliders = Physics.OverlapSphere(this.transform.position, separationDistance); //以当前位置为中心,separationDistance为半径
foreach (Collider c in colliders)
{
if (c!=null&&c.gameObject!=this.gameObject) //不添加自身
{
separationNeighbors.Add(c.gameObject);
}
}
//计算分离的力
foreach (GameObject neighbor in separationNeighbors)
{
Vector3 dir = transform.position - neighbor.transform.position;//相反的方向
separationForce += dir.normalized/dir.magnitude; //分离的力单位化除以dir的长度改变力的大小
}
if (separationNeighbors.Count>0) //邻居不能为空,否则无限远离
{
separationForce *= separationWeight;
sumForce += separationForce;
}
#endregion
#region 队列的力
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; //avgDir就是want方向-当前方向=alignmentForce,want与当前方向越近力越小
alignmentForce *= alignmengWight;
sumForce += alignmentForce;
}
}
#endregion
#region 聚集的力
if (separationNeighbors.Count<0||alignmentNeighbors.Count>0)
{
//计算中心点
Vector3 center = Vector3.zero;
foreach (GameObject item in alignmentNeighbors)
{
center += item.transform.position;
}
center /= alignmentNeighbors.Count;//得到中心点
Vector3 dir2Center = center - transform.position;//施加力的方向
cohesionForce += dir2Center;
cohesionForce *= cohesionWight;
sumForce += cohesionForce;
}
#endregion
//保持恒定飞行速度的力
Vector3 engineForce = startVelocity - velocity;//want方向-当前方向
sumForce += engineForce * 0.3f;
}
#endregion
private void Start()
{
startVelocity = velocity;
InvokeRepeating("CalcForce", 0, checkInterval);
ani = GetComponentInChildren<Animation>();
Invoke("PlayAnim", Random.Range(0, animRandom));
}
private void PlayAnim()
{
ani.Play();
startVelocity = velocity;
}
private void Update()
{
Vector3 a = sumForce / m; //加速度
velocity += a * Time.deltaTime;
//transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(velocity), Time.deltaTime); //自身的朝向就是飞行的方向
transform.rotation = Quaternion.LookRotation(velocity);
transform.Translate(velocity * Time.deltaTime, Space.World);
}
}