本仓库中代码为某大厂公开课第十周的课后作业,通过MyFish类和MyFlocking类实现,是基于传统Boids算法的近似模拟版本。使用UE5.4纯C++语言编写。
| 参数 | 描述 |
|---|---|
| CoefficientOfLeader | 控制普通鱼向领导鱼位置移动的力度 |
| CoefficientOfRepulsion | 控制鱼之间相互排斥的力度 |
| CoefficientOfLeaderVelocity | 控制普通鱼向领导鱼速度方向对齐的力度 |
| RadiusOfLeaderFish | 领导鱼随机移动的范围半径 |
| UpdateTargetTime | 领导鱼更新目标位置的时间间隔 |
- AMyFlocking: 鱼群控制器,管理所有鱼的生成与行为规则
- AMyFish: 单个鱼的行为实现,处理自身的运动与物理
本项目基于简化的Boids算法实现:
- 领导者-追随者模式:设置一条特殊的领导鱼,其他普通鱼会跟随它
- 三种运动力的平衡:
- 向领导鱼位置靠近的力(内聚力)
- 鱼与鱼之间的排斥力(分离力)
- 向领导鱼速度方向对齐的力(对齐力)
- 领导鱼行为:领导鱼会在指定半径内随机移动,定期更新目标位置
鱼群控制器会在初始化时生成指定数量的鱼:
void AMyFlocking::SpawnFish()
{
// 在随机位置生成所有鱼
for (int32 i = 0; i < NumOfFish; i++)
{
FVector SpawnLocation = FMath::VRand() * 100.f;
SpawnLocation.Z = 0.f;
AActor* Fish = GetWorld()->SpawnActor<AActor>(FishClass, GetActorLocation() + SpawnLocation, SpawnLocation.Rotation());
if (Fish)
FishArray[i] = Fish;
}
}鱼群控制器通过定时器定期更新所有鱼的行为:
void AMyFlocking::Update()
{
UpdateLeaderFish(); // 更新领导鱼行为
SetFishAccelerationDirection(); // 更新普通鱼行为
}领导鱼会定期更新随机目标位置,并向该位置移动:
void AMyFlocking::UpdateTarget()
{
FVector RandomVector = FMath::VRand();
RandomVector.Z = FMath::RandRange(-0.2f, 0.2f); // 限制垂直方向移动范围
TargetLocation = RandomVector * RadiusOfLeaderFish + GetActorLocation();
}普通鱼受三种力的影响:
- 向领导鱼的位置移动的力(与距离成正比)
- 与最近鱼的排斥力(与距离成反比的平方)
- 向领导鱼速度方向对齐的力(固定系数)
在UE编辑器中,将MyFlocking类拖入场景,并设置FishClass为MyFish类的蓝图子类(注意替换代码中的<项目名>)。
可以在编辑器中调整以下参数来改变鱼群行为:
- CoefficientOfLeader:增大该值会使普通鱼更紧密地追随领导鱼
- CoefficientOfRepulsion:增大该值会使鱼群更分散
- CoefficientOfLeaderVelocity:增大该值会使鱼群方向更一致
- RadiusOfLeaderFish:增大该值会扩大鱼群活动范围
- UpdateTargetTime:增大该值会使领导鱼目标变化更缓慢
- 未实现寻路算法实现鱼群避障
- 仅粗略了解Boids算法便着手近似实现,没有实现完整的Boids算法三原则
- 存在较大的性能开销问题
- 相关参数在近似计算中影响非线性且不明确,对参数进行调整可能会出现意外的情况