当前位置: 首页 > news >正文

Boids算法

在Unity中实现了 Boids 算法,实现类鸟运动行为模拟。该模拟从单个 boid 遵循一组规中产生复杂的涌现行为。下面程序实现行为模拟,加ComputerShader运算优化。

主要规则
Boids 算法由 Craig Reynolds 于 1986 年创建,是用于描述“鸟类物体”的术语。在这个模拟中,复杂的涌现行为来自简单的规则:
● 分离:检测某个范围内的所有类鸟的位置,计算出质心,然后产生一个远离质心的速度
● 平行:检测某个范围内的所有类鸟的速度,计算出平均速度,然后产生一个与平均速度方向一致的速度
● 内聚:检测某个范围内(与分离规则的范围不同)的所有类鸟的位置,计算出质心,然后产生一个指向质心的速度

同时可以应用额外的规则来创建更复杂、更有趣的行为。在本工程中添加了3条额外的规则:

  1. boid会加速或减速以匹配目标速度
  2. 鸟群会被方框边缘排斥
  3. 鸟群会避开被标记障碍的物体
    Boids 模型代码

Boid类

变量avgFlockHeading、avgAvoidanceHeading、centreOfFlockmates是三条基本规则的核心数据。

/// <summary>
/// 当前速度
/// </summary>
Vector3 velocity;
// To update:
/// <summary>
/// 鸟群平均航向
/// </summary>
public Vector3 avgFlockHeading;
/// <summary>
/// 鸟群平均躲避速度
/// </summary>
public Vector3 avgAvoidanceHeading;
/// <summary>
/// 鸟群中心点
/// </summary>
public Vector3 centreOfFlockmates;
/// <summary>
/// 鸟群数量
/// </summary>
public int numPerceivedFlockmates;

该方法应用所有规则并及时推进 boids 模型。每个规则的距离和权重在参数中定义。

public void UpdateBoid () {// 当前帧检测所产生的速度Vector3 acceleration = Vector3.zero;if (target != null) {// 计算目标速度,方向*飞向目标的速度Vector3 offsetToTarget = (target.position - position);acceleration = SteerTowards (offsetToTarget) * settings.targetWeight;}// 如果观察半径内有鸟,则构成鸟群if (numPerceivedFlockmates != 0) {// 获取偏移值Vector3 offsetToFlockmatesCentre = (centreOfFlockmates - position);// 获取对齐力var alignmentForce = SteerTowards (avgFlockHeading) * settings.alignWeight;// 获取内聚力var cohesionForce = SteerTowards (offsetToFlockmatesCentre) * settings.cohesionWeight;// 获取分离力var seperationForce = SteerTowards (avgAvoidanceHeading) * settings.seperateWeight;// 计算帧当前速度acceleration += alignmentForce;acceleration += cohesionForce;acceleration += seperationForce;}// 当前飞向是否碰撞障碍if (IsHeadingForCollision ()) {// 获取避免碰撞分享Vector3 collisionAvoidDir = ObstacleRays ();// 计算避免碰撞的力Vector3 collisionAvoidForce = SteerTowards (collisionAvoidDir) * settings.avoidCollisionWeight;acceleration += collisionAvoidForce;}// 当前帧速度var frameVelocity = velocity + acceleration * Time.deltaTime;float speed = frameVelocity.magnitude;Vector3 dir = frameVelocity / speed;// 限制最大速度speed = Mathf.Clamp (speed, settings.minSpeed, settings.maxSpeed);velocity = dir * speed;forward = dir;
}private void LateUpdate()
{// 修改当前帧位置和朝向cachedTransform.position += velocity * Time.deltaTime;cachedTransform.forward = forward;position = cachedTransform.position;   
}bool IsHeadingForCollision () {// 检测是否碰撞RaycastHit hit;if (Physics.SphereCast (position, settings.boundsRadius, forward, out hit, settings.collisionAvoidDst, settings.obstacleMask)) {return true;} else { }return false;
}Vector3 ObstacleRays () {// 存储了n个方向Vector3[] rayDirections = BoidHelper.directions;// 检测那个分享可以避免碰撞for (int i = 0; i < rayDirections.Length; i++) {Vector3 dir = cachedTransform.TransformDirection (rayDirections[i]);Ray ray = new Ray (position, dir);if (!Physics.SphereCast (ray, settings.boundsRadius, settings.collisionAvoidDst, settings.obstacleMask)) {return dir;}}return forward;
}Vector3 SteerTowards (Vector3 vector) {// 速度与当前阶段计算的速度相减,得到一个合速度Vector3 v = vector.normalized * settings.maxSpeed - velocity;return Vector3.ClampMagnitude (v, settings.maxSteerForce);
}

Boid管理类

计算各boid的平行、分离、内聚速度。

void Update () {if (boids != null) {int numBoids = boids.Length;// 设置所有的boid数据var boidData = new BoidData[numBoids];for (int i = 0; i < boids.Length; i++) {boidData[i].position = boids[i].position;boidData[i].direction = boids[i].forward;}// 创建一个computerbuff,并添加boid数据var boidBuffer = new ComputeBuffer (numBoids, BoidData.Size);boidBuffer.SetData (boidData);compute.SetBuffer (0, "boids", boidBuffer);compute.SetInt ("numBoids", boids.Length);compute.SetFloat ("viewRadius", settings.perceptionRadius);compute.SetFloat ("avoidRadius", settings.avoidanceRadius);// 设置computershader 数据int threadGroups = Mathf.CeilToInt (numBoids / (float) threadGroupSize);compute.Dispatch (0, threadGroups, 1, 1);// 从computerbuff中获取数据boidBuffer.GetData (boidData);// 设置回数据 并更新boidfor (int i = 0; i < boids.Length; i++) {boids[i].avgFlockHeading = boidData[i].flockHeading;boids[i].centreOfFlockmates = boidData[i].flockCentre;boids[i].avgAvoidanceHeading = boidData[i].avoidanceHeading;boids[i].numPerceivedFlockmates = boidData[i].numFlockmates;boids[i].UpdateBoid ();}boidBuffer.Release ();}
}
/// <summary>
/// ComputerShader需要的数据
/// </summary>
public struct BoidData {public Vector3 position;public Vector3 direction;public Vector3 flockHeading;public Vector3 flockCentre;public Vector3 avoidanceHeading;public int numFlockmates;public static int Size {get {return sizeof (float) * 3 * 5 + sizeof (int);}}
}

ComputerShader,每个线程计算1个boid数据

#pragma kernel CSMain
static const int threadGroupSize = 1024;struct Boid {float3 position;float3 direction;float3 flockHeading;float3 flockCentre;float3 separationHeading;int numFlockmates;
};RWStructuredBuffer<Boid> boids;
int numBoids;
float viewRadius;
float avoidRadius;[numthreads(threadGroupSize,1,1)]
void CSMain (uint3 id : SV_DispatchThreadID)
{// 计算boid感知半径是否存在其他鸟,后计算鸟群中心点、该鸟所在鸟群数量和鸟群的合方向float3 centerSize;for (int indexB = 0; indexB < numBoids; indexB ++) {if (id.x != indexB) {Boid boidB = boids[indexB];float3 offset = boidB.position - boids[id.x].position;float sqrDst = offset.x * offset.x + offset.y * offset.y + offset.z * offset.z;if (sqrDst < viewRadius * viewRadius) {boids[id.x].numFlockmates += 1;boids[id.x].flockHeading += boidB.direction;centerSize += boidB.position;if (sqrDst < avoidRadius * avoidRadius) {boids[id.x].separationHeading -= offset / sqrDst;}}}}boids[id.x].flockCentre = centerSize / boids[id.x].numFlockmates;
}

BoidSetting

变量的大小关系,是所偏向的力,代表着不同的规则,存在不同的表现。

    // Settingspublic float minSpeed = 2;public float maxSpeed = 5;// 感知半径public float perceptionRadius = 2.5f;// 躲避boid半径public float avoidanceRadius = 1;// 最大转向力public float maxSteerForce = 3;// 对齐力public float alignWeight = 1;// 内聚力public float cohesionWeight = 1;// 分离力public float seperateWeight = 1;// 偏向目标力public float targetWeight = 1;[Header ("Collisions")]public LayerMask obstacleMask;public float boundsRadius = .27f;public float avoidCollisionWeight = 10;public float collisionAvoidDst = 5;
}
http://www.gsyq.cn/news/24517.html

相关文章:

  • 常见问题解决 --- 为什么我导出的apk不包含dex文件
  • 2025年润滑油厂家推荐排行榜,工业润滑油,汽车润滑油,发动机润滑油,甲醇发动机润滑油,全合成润滑油,长效发动机润滑油公司推荐!
  • 10.19 —— (VP)2022icpc西安
  • Redis 有序集合解析 - 指南
  • 科技领域导师制度与因果分析方法解析
  • 完整教程:使用Celery处理Python Web应用中的异步任务
  • 2025年UV光源厂家推荐排行榜,UV面光源,UV LED点光源,UV LED面光源,UV LED固化机公司精选
  • 比赛与好题记录(2025 9-10)
  • 函数简单传入参数的汇编分析 - 指南
  • 数据类型转换以及内存溢出
  • 2025年UV胶点胶机厂家推荐排行榜,全自动/智能/视觉定位/纽扣/拉链头/拉片/商标/钥匙扣/五金/徽章/线圈/硅胶点胶机公司推荐!
  • 鸿蒙设备开发-gpio控制
  • 如何在Java中进行多线程编程
  • 零售行业绩效流程推行难点及 Tita 目标绩效一体化管理方案
  • 《探索C语言中数组的奥秘(下)》 - 教程
  • [转]学习指南 - PL-600:Microsoft Power Platform 解决方案架构师
  • Vue中keep-alive实现原理解析
  • 深入学习Spring Boot框架
  • java语言程序设计类与对象课后作业 - 20243867孙堃2405
  • java流程控制。
  • 2025年扑灭司林厂家推荐排行榜,高效环保扑灭司林,专业生产与市场口碑深度解析!
  • 3 分钟搞懂 Java 中 this 关键字的用法
  • 折腾笔记[32]-windows部署vscode-server及使用命令行编译c#.net工程
  • 2025润滑油厂家推荐:三特石化全合成长效发动机油,品质卓越!
  • Java 类与对象实践:从代码验证到四则运算开发
  • 2025手持光谱仪厂家推荐:一诺机电精准分析,便携高效检测首选!
  • DP优化:四边形不等式、决策单调性与凸性
  • WPS中Mathtype插件消失不见解决方法
  • 2025年塑料托盘厂家推荐排行榜,网格川字/九脚/田字/双面塑料托盘,平板/吹塑/注塑/焊接/印刷/组装款/高矮脚/反川字/立体库托盘公司精选!
  • 物理感知 RTL 合成