Как синхронизация XNA работает?

Как XNA поддерживает последовательную и точную частоту кадров на 60 кадр/с? Кроме того, как это поддерживает такую точную синхронизацию, не привязывая ЦП в 100%?

5
задан Callum Rogers 8 May 2010 в 22:37
поделиться

4 ответа

Я не знаю, как именно XNA это делает, но, играя с OpenGL несколько лет назад, я сделал то же самое, используя очень простой код.

По сути, я предполагаю, что в XNA есть какой-то цикл рендеринга, он может быть интегрирован или не интегрирован со стандартным циклом четной обработки, но для примера допустим, что это не так. в этом случае вы могли бы написать что-нибудь вроде этого.

TimeSpan FrameInterval =  TimeSpan.FromMillis(1000.0/60.0);
DateTime PrevFrameTime = DateTime.MinValue;
while(true)
{
    DateTime CurrentFrameTime = DateTime.Now;
    TimeSpan diff = DateTime.Now - PrevFrameTime;
    if(diff < FrameInterval)
    {
        DrawScene();
        PrevFrameTime = CurrentFrameTime;
    }
    else
    {
        Thread.Sleep(FrameInterval - diff);
    }
}

На самом деле вы, вероятно, использовали бы что-то вроде Environment.Ticks вместо DateTimes (это было бы более точно), но я думаю, что это иллюстрирует суть. Это должно вызывать drawScene только около 60 раз в секунду, а в остальное время поток будет находиться в спящем режиме, поэтому он не потребует процессорного времени.

2
ответ дан 14 December 2019 в 13:29
поделиться

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

Если запустить игру в режиме отладки, можно получить гораздо больше кадров в секунду - например, пустой шаблон стартера на моем ноутбуке в режиме отладки работает более чем на 1000 кадров в секунду.

При этом фреймворк XNA в выпущенной игре будет делать все возможное, чтобы работать со скоростью 60 кадров в секунду - но код, который вы включили в свой проект, может снизить эту производительность. Например, если что-то постоянно сбрасывает сборку мусора, то обычно это приводит к падению fps в игре, или если в методах обновления или рисования используется сложная математика, то они должны срабатывать каждый кадр, что обычно является чрезмерным. Есть несколько вещей, которые следует иметь в виду, чтобы сделать вашу игру настолько упрощенной, насколько это возможно.

Если вы спрашиваете, как фреймворк XNA обеспечивает этот потолок, то я не могу объяснить, но могу сказать, что в зависимости от того, как вы компонуете свой код, и что вы можете сделать, это может определенно негативно повлиять на это число, и это не всегда связано с процессором. В случае со сборкой мусора это просто очистка оперативной памяти, которая может вообще не показывать всплеска использования процессора, но может повлиять на FPS, в зависимости от количества мусора и интервала, с которым он должен выполняться.

0
ответ дан 14 December 2019 в 13:29
поделиться

Хотя код Люка выше теоретически правильный, используемые методы и свойства - не лучший выбор:

  • Поскольку точность DateTime.Now составляет всего около 30 мс (см. C# DateTime.Now precision и плюс-минус 20 мс), его использование для высокопроизводительного тайминга нежелательно (60 FPS - это 16 мс). System.Diagnostics.Stopwatch является таймером для реального времени .NET
  • Thread.Sleep страдает той же проблемой точности/разрешения и не гарантированно спит только указанное время

Текущий XNA FX, похоже, подключается к циклу сообщений Windows и выполняет свое внутреннее предварительное обновление каждый шаг и вызывает Game. Update только если время, прошедшее с момента последнего обновления, соответствует заданной частоте кадров (например, каждые 16 мс для настроек по умолчанию). Если вы хотите действительно узнать, как XNA FX выполняет свою работу Reflector - ваш друг :)

Случайная заметка: Еще во времена XNA GameStudio 1.0 Alpha/Beta было довольно много сообщений в блогах об "идеальном игровом цикле WinForms", хотя сейчас я не могу их найти...

.
4
ответ дан 14 December 2019 в 13:29
поделиться

Вы можете прочитать все о том, как был реализован таймер XNA здесь Время игры в XNA Game Studio , но в основном он будет пытаться выдержать 1/60 секунды, прежде чем снова продолжить цикл, также обратите внимание, что обновление может вызываться несколько раз перед рендерингом, если XNA нужно «наверстать упущенное».

0
ответ дан 14 December 2019 в 13:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: