还差一个对齐,不然就乱飞
分散算法请看上一篇文章: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);}}//平均点位置为0averagePosition = 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);}
}