en造数据结构与算法C# 用Unity实现简单的群组行为算法 之 分散
因为还没写聚集并且材质没有设置摩擦系数,所以出现了这种刚体受力得到初速度却无法减少,从而乱飞的情况
本教程部分代码师承于siki学院siki老师的人工智能编程这一案例,我认为自己的水平有限,老师的写法太过高级,所以就写了一下自己想着能实现的算法,没想到还真成了,嘻嘻
演示
第一版
第二版
思路
1.确定检测范围
自然是用到Unity的范围检测了,unity保姆级教程之 射线检测_unity 射线-CSDN博客
2.存起来邻居鸟
自然用到线性表,你问我什么是线性表?
恩造数据结构与算法c# 用数组实现List-CSDN博客
不过嘛,这里用c#官方造好的轮子即可,List<T>
3.确定力的合力与方向
自然用到向量的知识,注意朝向哦
unity保姆级教程之向量篇_unity 向量-CSDN博客
4.施加力
第一版演示的是用直接刚体加力,不过这样会造成飞的太快,并且加力大小也不会根据鸟之间的距离发生改变,所以就小小优化了一下
上代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BoidsCode : MonoBehaviour
{
Rigidbody rb;
//鸟群存储线性表
public List<GameObject> seprationNeighbors = new List<GameObject>();
//separation分离 aliganment对齐 cohesion凝聚
public Vector3 separationForce = Vector3.zero;
public Vector3 aliganmentForce = Vector3.zero;
public Vector3 cohesionForce = 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()
{
//清空邻居鸟的列表
seprationNeighbors.Clear();
//检测到范围内所有的鸟
Collider[] colliders = Physics.OverlapSphere(transform.position, checkDistance);
foreach (Collider collider in colliders) {
if (collider!=null && collider!=this.gameObject)
{
//添加到列表里面
seprationNeighbors.Add(collider.gameObject);
}
}
separationForce = Vector3.zero;
foreach (GameObject brid in seprationNeighbors) {
//设定方向
Vector3 forceDirection =(this.transform.position - brid.transform.position).normalized;
//直接施加力以作实验
//rb.AddForce(forceDirection,ForceMode.Impulse);
//或 这样写,好处就是可以根据距离累加力
if (forceDirection.magnitude > 0) {
separationForce += forceDirection / forceDirection.magnitude;
}
}
rb.AddForce(separationForce, ForceMode.Impulse);
}
}