在过去的几周里,我一直在学习 C#/XNA 以尝试制作游戏,所以这可能是一个明显的新手问题,但这里有:
我一直在制作一个相当简单的 2D 游戏,所以我有一个大约 1000 个对象(NPC)的列表,并且我非常频繁地迭代它们以对每个对象进行距离检查。问题是当我增加距离时,一切都会大大减慢到无法玩游戏的程度,我真的不明白为什么。
当距离很短时(如果所有对象都在一个 800x480 的世界大小范围内),它工作得很好,但是当它们增加时(例如,8000x4800 的世界大小),我的性能会下降。
这是一些相关的代码(显然,不是全部,因为这将是太多的东西,但这是正在发生的事情的要点):
List<Human> humans;
List<Enemy> enemies;
public void Update(City city, float gameTime)
{
humans = city.GetHumans();
enemies = city.GetEnemies();
for (int h = 0; h < humans.Count; h++)
{
Vector2 human_position = humans[h].position;
Vector2 nearestEnemyPosition = Vector2.Zero;
for (int e = 0; e < enemies.Count; e++)
{
Vector2 enemy_position = enemies[e].position;
float distanceToEnemy = Vector2.DistanceSquared(human_position, enemy_position);
if (distanceToEnemy < distanceToNearestEnemy)
{
distanceToNearestEnemy = distanceToEnemy;
nearestEnemyPosition = enemy_position;
}
if (distanceToNearestEnemy < 2500f)
{
logic code here (very little performance impact)
}
}
for (int hh = 0; hh < humans.Count; hh++)
{
if (h == hh)
{
continue;
}
if (humanMoved == true)
{
continue;
}
Vector2 other_human_position = humans[hh].position;
if (Vector2.DistanceSquared(human_position, other_human_position) < 100f)
{
do more stuff here (movement code, no performance impact)
}
对于敌人列表,我也有几乎相同的循环。
制作它们的代码在这里:
foreach (Human human in this.humans)
{
Vector2 position = new Vector2(random.Next(800), random.Next(480));
human.Spawn(position);
}
这工作正常。我得到了 60fps,它非常流畅,一切都运行得很好。但是,如果我这样做:
foreach (Human human in this.humans)
{
Vector2 position = new Vector2(random.Next(8000), random.Next(4800));
human.Spawn(position);
}
一切都坦克,我得到1fps。这看起来很奇怪,更大的数字真的会使 DistanceSquared 函数的计算时间更长吗?为什么?还是有其他可能导致我失踪的原因?
我已经运行了几个性能分析器,但它们没有告诉我任何有用的信息,只是 DistanceSquared 占用了我绝大多数的 CPU 周期。如果它是 800x480 的正常值,那么我的游戏时间只有 38% 用于该循环。当我将数字从 800->8000/480->4800 更改时,我 90% 的时间都花在了循环中。这并不是说有更多的对象要调用,也不是要进行更多的数学运算,而是相同的数学运算,只是数字更大,那么为什么会有如此巨大的差异呢?