en造数据结构与算法C# 用Unity实现简单的群组行为算法 之 聚集
还差一个对齐,不然就乱飞
分散算法请看上一篇文章:en造数据结构与算法C# 用Unity实现简单的群组行为算法 之 分散-CSDN博客
演示(在分散的基础上)
思路
1.确定检测范围
其实,可以沿用上一篇章中分散的检测范围,为什么?
1.自然界中的鸟的分离和聚集是同时发生的,使用一个检测范围更加方便计算
2.因为每一只鸟身上都有一个群组脚本,所以可以把检测范围当作分割线来看,这样在检测范围内的鸟称作邻居,只有邻居才会受到影响,不然距离你十万八千里的外的鸟一把抓住,顷刻拉近也不合适,如图紫色线为关系连线
2.确定拉近位置
自然是邻居鸟的位置相加后的平均值了
3.确定力的合力与方向
原理和这张图大差不差,我就不再费事画了
上代码
分离出来的代码
cohesionForce = Vector3.zero; //凝聚力重设
foreach (GameObject bird in separationNeighbors) {
//设定分离力的方向
Vector3 spForceDirection = (this.transform.position - bird.transform.position).normalized;
if (spForceDirection.magnitude > 0) {
separationForce += spForceDirection / spForceDirection.magnitude;
}
//得到鸟群位置(加起来的和)
averagePosition += bird.transform.position;
}
//计算平均位置
if (separationNeighbors.Count > 0) {
averagePosition /= separationNeighbors.Count;
}
//设定凝聚力的方向
Vector3 cohesionDirection = (averagePosition - transform.position).normalized;
if (cohesionDirection.magnitude > 0) {
cohesionForce += cohesionDirection;
}
//施加分离力
rb.AddForce(separationForce, ForceMode.VelocityChange);
//施加凝聚力
rb.AddForce(cohesionForce, ForceMode.VelocityChange);
}
总和代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BoidsCode1 : MonoBehaviour {
Rigidbody rb;
//鸟群存储线性表
public List<GameObject> separationNeighbors = new List<GameObject>();
//separation分离 alignment对齐 cohesion凝聚
public Vector3 separationForce = Vector3.zero;
public Vector3 alignmentForce = Vector3.zero;
public Vector3 cohesionForce = Vector3.zero;
public Vector3 averagePosition = Vector3.zero;
public Vector3 sumForce;
//检测间隔
public float checkInterval = 0.35f;
//检测距离
public float checkDistance = 2;
private void Awake() {
rb = GetComponent<Rigidbody>();
}
private void Start() {
InvokeRepeating("CalcForce", 0, checkInterval);
}
//计算函数
private void CalcForce() {
//清空邻居鸟的列表
separationNeighbors.Clear();
//检测到范围内所有的鸟
Collider[] colliders = Physics.OverlapSphere(transform.position, checkDistance);
foreach (Collider collider in colliders) {
if (collider != null && collider.gameObject != this.gameObject) {
//添加到列表里面
separationNeighbors.Add(collider.gameObject);
}
}
//平均点位置为0
averagePosition = Vector3.zero;
separationForce = Vector3.zero; //分离力重设
cohesionForce = Vector3.zero; //凝聚力重设
alignmentForce = Vector3.zero; //对齐力重设
foreach (GameObject bird in separationNeighbors) {
//设定分离力的方向
Vector3 spForceDirection = (this.transform.position - bird.transform.position).normalized;
if (spForceDirection.magnitude > 0) {
separationForce += spForceDirection / spForceDirection.magnitude;
}
//得到鸟群位置(加起来的和)
averagePosition += bird.transform.position;
}
//计算平均位置
if (separationNeighbors.Count > 0) {
averagePosition /= separationNeighbors.Count;
}
//设定凝聚力的方向
Vector3 cohesionDirection = (averagePosition - transform.position).normalized;
if (cohesionDirection.magnitude > 0) {
cohesionForce += cohesionDirection;
}
//施加分离力
rb.AddForce(separationForce, ForceMode.VelocityChange);
//施加凝聚力
rb.AddForce(cohesionForce, ForceMode.VelocityChange);
}
}