XNA запаздывает, когда окно имеет фокус - PullRequest
0 голосов
/ 02 сентября 2011

Я занимаюсь разработкой игр для xna с использованием XNA 3.1, и я заметил проблему с некоторыми играми, когда они отстают, несмотря на то, что в системе достаточно ресурсов для их обработки, а также необъяснимым избытком использования процессора.Когда окно из игры находится в фокусе, процесс № 1 (в диспетчере задач) переходит на 100% -ное использование, и игра демонстрирует признаки незначительного лага (в основном, когда звуковые эффекты повторяются в последовательности).Когда игра теряет фокус окна, она продолжает рисовать и обновлять в режиме реального времени, но использование процесса уменьшается, а отставание исчезает.

Я проверил это с различными играми, и результаты остались прежними, доказывая, что это не имеет никакого отношения к моему коду или эффективности кода.

Является ли эта проблема изолированной для Xna 3.1, и есть ли исправление для нее?Или мне просто нужно перейти на 4.0 и надеяться, что мои игры не используют ничего, что не было бы обратно совместимо?

Ответы [ 3 ]

0 голосов
/ 03 сентября 2011

XNA добавить сон, когда окно не в фокусе! Я решил эту проблему некоторое время назад, изменив класс Game и изменив способ, которым класс Game понимает, активна его форма или нет.

Насколько я знаю, нет способа отключить это поведение без изменения поведения класса Game с помощью кода.

В частности, способ, который я нашел некоторое время назад, это настоящий хак \ quirk! Очень грязное решение, но единственный способ, который я нашел.

public class MyGame
{
    private MethodInfo pActivate;

    public MyGame()
    {
        // We need to access base HostActivate method, that unfortunally, is private!
        // We need to use reflection then, of course this method is an hack and not a real solution!
        // Ask Microsoft for a better implementation of their class!

        this.pActivate = typeof(Game).GetMethod("HostActivated", BindingFlags.NonPublic | BindingFlags.Instance);
    }

    protected sealed override void OnDeactivated(object sender, EventArgs args)
    {
        base.OnDeactivated(sender, args);

        // Ok, the game form was deactivated, we need to make it believe the form was activated just after deactivation.

        if (!base.Active)
        {
            // Force activation by calling base.HostActivate private methods.
            this.pActivate.Invoke(this, new object[] { sender, args });
        }
    }
}
0 голосов
/ 03 сентября 2011

Проблема может возникнуть из-за сборщика мусора. Каждый раз, когда запускается сборщик мусора, частота кадров может падать на секунду или две, хотя в Windows это не должно быть проблемой.

Добавьте эту строку в свой код и посмотрите, сколько кучи памяти генерируется. Каждый раз, когда значение уменьшается, запускается сборщик мусора.

 SpriteBatch.DrawInt64(FONT, GC.GetTotalMemory(false) / 1000 /* in kilobytes */, new Vector2(5, 30), Color.White, 0f);

SpriteBatch.DrawInt64 является расширением SpriteBatch, которое не генерирует мусор для int, long и т. Д. Вы можете альтернативно просто использовать SpriteBatch.DrawString (..., (GC.GetTotalMemory (false) / 1000) .ToString (), .. .)

SpriteBatchExtensions.cs: http://pastebin.com/z9aB7zFH

0 голосов
/ 03 сентября 2011

XNA, по моему опыту, работает до 60 кадров в секунду, когда находится в фокусе, и со скоростью около 20 кадров в секунду, когда не в фокусе. Однако, если вы установили IsFixedTimeStep = false;, игра будет работать так быстро, как только возможно, когда процесс находится в фокусе. С моей игрой на моей машине она работает со скоростью около 500-700 кадров в секунду. Это также , привязанное к количеству Update() вызовов, которые происходят. Так что моя игра также обновляется 500-700 раз в секунду.

Моя ставка в том, что вы отключили фиксированный временной интервал, и огромное количество вызовов на обновление и отрисовку занимают 100% вашего ядра, и это мешает вашей музыке. Я бы порекомендовал удалить строку IsFixedTimeStep = false;, если она там есть. Если эта строка не существует в вашем коде, это не проблема, хотя я бы поспорил, что ваше обновление или ничья делают больше работы, чем должно быть.

Только что заметил это в моей собственной игре, у меня есть оператор Console.WriteLine (для отладки) в моем цикле обновления, это вызывает большое отставание.

...