0

我正在使用 XNA 3.1 为 xna game studion 开发,我注意到一些游戏存在问题,尽管系统有足够的资源来处理它们,但它们仍然滞后,而且处理器使用量莫名其妙。当游戏窗口处于焦点时,进程#1(在任务管理器中)进入 100% 使用率,并且游戏显示出轻微滞后的迹象(当声音效果按顺序重复时很明显)。当游戏失去窗口焦点时,它会继续实时绘制和更新,但进程使用量减少,滞后消失。

我用各种游戏对此进行了测试,结果还是一样,证明它与我的代码或代码效率无关。

这是一个与 Xna 3.1 无关的问题,是否有解决方案?还是我只需要切换到 4.0 并希望我的游戏不使用任何不向后兼容的东西?

4

3 回答 3

0

根据我的经验,XNA 在对焦时每秒可运行高达 60 帧,而在失焦时则以每秒约 20 帧的速度运行。但是,如果您已设置IsFixedTimeStep = false;游戏将在该过程处于焦点时以尽可能快的速度运行。使用我的游戏,在我的机器上,它以大约 500-700 fps 的速度运行。这Update()发生的呼叫数量有关。所以我的游戏也是每秒更新 500-700 次。

我敢打赌,您已经禁用了固定时间步长,并且大量的 Update 和 Draw 调用正在消耗您 100% 的核心,并且会干扰您的音乐。IsFixedTimeStep = false;如果它在那里,我会建议删除该行。如果您的代码中不存在该行,则这不是问题,尽管我敢打赌您的 Update 或 Draw 所做的工作超出了应有的范围。

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

于 2011-09-02T20:04:14.427 回答
0

当窗口不在焦点时,XNA 添加睡眠!我前段时间解决了这个问题,覆盖了 Game 类并改变了 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 });
        }
    }
}
于 2011-09-02T20:08:40.430 回答
0

垃圾收集器可能会出现此问题。每次垃圾收集器运行时,帧速率可能会下降一两秒,但在 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

于 2011-09-02T22:09:51.183 回答