当前位置: 首页 > 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.hskmm.com/?act=detail&tid=34427

相关文章:

  • Spring Cloud RabbitMQ 详解:从基础概念到秒杀实战 - 详解
  • 2025年安装厂家权威推荐榜单:管道/电气/生物医药工厂机电/暖通空调/空压系统/纯水系统/厂房通风/车间配电/机械设备/工业设备安装公司精选
  • 35跬步本手@数学学习+计算机学习+语言学习@20251019
  • 【容器日志采集】【 四】消费kafka保存到es
  • 嵌入式实验3串口通信---任务二串口传输文件实验
  • 2025年润滑油厂家推荐排行榜,工业润滑油,汽车润滑油,发动机润滑油,甲醇发动机润滑油,全合成润滑油,长效发动机润滑油公司推荐!
  • 题解:loj6703 小 Q 的序列
  • 【容器日志采集】【二】fluent-bit配置文件
  • 【容器日志采集】【三】创建daemonsets采集日志发送到kafka
  • 2025年保洁公司权威推荐榜单:驻场/钟点/开荒/外包/商场/办公楼/工厂/医院/企业保洁服务优选指南
  • 2025年电源适配器厂家推荐排行榜,电脑/手机/平板电源适配器,高品质充电解决方案!
  • 解题报告-洛谷SCP2025T2 P14254 分割(divide)
  • 深入解析:Spring Cloud Netflix Eureka:从微服务基础到高可用集群实战
  • 2025.10.19——1绿1蓝
  • 别看我只是一只羊
  • 10.19 —— (VP)2022icpc西安
  • 2025年储罐源头厂家推荐排行榜,钢衬塑/钢塑复合/化工/防腐/PE/盐酸/硫酸/聚丙烯/不锈钢/次氯酸钠储罐公司精选!
  • 26-wsl-nginx-chinese-encoding-fix
  • win10-减少广告的三个操作
  • java方法
  • 变量名越怪,JVM 越快?
  • 深入解析:CPU调度算法简记
  • 2025年TYPE-C母座厂家推荐排行榜,防水/板上/沉板/立插/立贴/侧插/立式/插座/接口/插头/5A大电流/高速/TID认证公司精选
  • 在AI技术唾手可得的时代,挖掘用户真实需求成为制胜关键——某知名系统工具需求探索
  • 2025年通风气楼/通风天窗厂家推荐排行榜,圆拱型/电动/一字型/钢结构/流线型/屋顶自然/三角型/排烟/采光/启闭式/薄型/成品/消防联动/工厂/屋面/开敞式/启闭式排烟/通风设备公司推荐!
  • 科技领域导师制度与因果分析方法解析
  • 比赛与好题记录(2025 9-10)
  • 全面详解 C++std::vector用法指南
  • Visual Studio Code 初步配置指南(Windows端)
  • 2025年UV光源厂家推荐排行榜,UV面光源,UV LED点光源,UV LED面光源,UV LED固化机公司精选