当窗口有焦点时XNA延迟

本文关键字:XNA 延迟 焦点 窗口 | 更新日期: 2023-09-27 18:07:29

我正在使用xna 3.1为xna游戏工作室开发游戏,并且我注意到一些游戏存在一个问题,即尽管系统拥有足够的资源来处理它们,但它们却会出现延迟,并且伴随着无法解释的过多处理器使用。当游戏窗口处于焦点状态时,进程#1(在任务管理器中)的使用率将达到100%,并且游戏显示出轻微延迟的迹象(当声音效果按顺序重复时非常明显)。当游戏失去窗口焦点时,它会继续实时绘制和更新,但进程使用率会下降,延迟也会消失。

我已经用各种游戏测试了这个,结果保持不变,证明它与我的代码或代码效率无关。

这个问题是孤立的Xna 3.1,有修复吗?或者我只需要切换到4.0,并希望我的游戏不会使用任何不向后兼容的东西?

当窗口有焦点时XNA延迟

可能是垃圾回收器导致的问题。每次垃圾收集器运行时,帧率可能会下降一到两秒,尽管在Windows上这应该不是问题。

将这行添加到代码中,看看生成了多少堆内存。每当该值下降时,就运行垃圾收集器。

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

SpriteBatch。drawwint64是一个SpriteBatch扩展,它不会在int, long等上产生垃圾。你也可以选择使用SpriteBatch.DrawString(…, (GC.GetTotalMemory(false)/1000).ToString(),…)

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

XNA,根据我的经验,在对焦时每秒运行60帧,在失焦时每秒运行约20帧。然而,如果你设置了IsFixedTimeStep = false;,游戏将在聚焦过程时尽可能快地运行。对于我的游戏,在我的机器上,它的运行速度大约是500-700 fps。这也是与发生的Update()调用的数量相关联。所以我的游戏也是每秒更新500-700次。

我打赌你已经禁用了固定的时间步长,大量的更新和绘制调用消耗了你100%的核心,它扰乱了你的音乐。我建议去掉IsFixedTimeStep = false;线,如果它在那里。如果这一行在你的代码中不存在,这不是问题,尽管我敢打赌你的更新或绘制做了比它应该做的更多的工作。

我在自己的游戏中注意到了这一点,我有一台主机。WriteLine语句(用于调试)在我的更新循环中,这会导致很多延迟。

XNA添加一个睡眠当窗口不在焦点!我在前一段时间解决了这个问题,重写Game类并改变Game类理解其形式是否活跃的方式。

没有办法,据我所知,不修改游戏类的行为与代码禁用此行为。

特别是,我前一段时间发现的方式是一个真正的黑客'怪癖!很不干净的解决方法,但这是我找到的唯一方法。

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 });
        }
    }
}