我正在为小型游戏进行简单的flok或群集模拟。
这种行为对我的需求来说是不错的,但表现并非如此。
基本上我有很多物体(士兵),需要在移动到航点时展开。
我在这里写了一个简单版本的代码:
List<Soldier> avoidList = new List<Soldier>();
foreach (Soldier s in gameWorld)
{
if (this == s)
continue;
if (Distance(s, this) <= 5)
{
avoidList.Add(s);
}
}
CalculateNewDirection(avoidList);
基本上,每个士兵都会检查场景中其他士兵的距离,并根据太近的士兵计算方向。
现在我正在浏览x ^ 2个对象。
因此,如果我有100个对象,我会运行100 ^ 2 = 10.000个对象,只是为了更新每个单独的对象avoidList。
如果我将它调到500个物体,我会运行250,000个物体。
Theres必须采用另一种更聪明的方式来做到这一点!
希望有人能赐教我:)
答案 0 :(得分:1)
在我的头顶上,看起来你在计算距离时正在做一个不必要的平方根。您可以检查平方距离,并检查平方常数。
此外,还有一项改进,如果你发现一名士兵要避开,另一名士兵也会避开第一名士兵。因此,如果您跟踪多个避免列表,则每对只需要检查一次。
这可以通过仅保存太靠近的对来完成。在伪代码中
for (int i = 0; i < numSoldiers - 1; ++i) {
for (int j = i + 1; j < numSoldiers; ++j) {
if (Distance(soldier[i], soldier[j]) < 5) {
closePairs.Add(new Pair(i, j));
}
}
}
// Calculate directions based on the pairs found.
这些是基本的优化。如果你需要更深入,你需要根据位置对士兵进行排序。如果你跟踪每个5个单位的士兵,那么超过2个方格的士兵就不会影响给定的士兵。
首先在X和Y轴上对士兵进行排序也会给出类似的机会,因为你知道如果一个轴上下一个人的距离大于半径,则无需检查距离。
这会让你获得更好的表现,但这取决于你的数据以及士兵通常的稀疏程度。