0

過去数週間、ゲームを作成するために C#/XNA を学習してきたので、これは明らかな初心者のことかもしれませんが、次のようになります。

私はかなり単純な 2D ゲームを作成しているので、1000 個までのオブジェクト (NPC) のリストがあり、それらを非常に頻繁に反復して、それぞれの距離チェックを行っています。問題は、距離を長くすると、すべてが大幅に遅くなり、ゲームがプレイできなくなることです。その理由はよくわかりません。

距離が短い場合 (すべてのオブジェクトが 1 つの 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);
        }

これはうまくいきます。私は 60 fps を取得し、それは完全にスムーズで、すべてが完璧に動作します。ただし、これを行うと:

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% がループに費やされます。呼び出すオブジェクトが増えたり、計算が増えたりするわけではありません。数値が大きくなるだけで同じ計算になるのに、なぜそんなに劇的な違いがあるのでしょうか?

4

1 に答える 1

0

計算の前に世界を [0-1,0-1] に正規化してみて、影響があるかどうかを確認してください。このようにして、ループコードはまったく同じになり、各位置は 0-1 の範囲になり、現実世界を計算します位置は、計算の最後にそれらを乗算するだけです

于 2013-02-21T06:00:33.733 に答える