当窗口具有焦点时 XNA 滞后

发布于 2024-12-02 14:44:50 字数 322 浏览 3 评论 0原文

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

我用各种游戏对此进行了测试,结果保持不变,证明它与我的代码或代码效率无关。

这是 Xna 3.1 独有的问题吗?有解决办法吗?或者我是否只需切换到 4.0 并希望我的游戏不要使用任何不向后兼容的东西?

I'm developing for xna game studion using XNA 3.1, and I've noticed a problem with some games, where they lag despite the system having plenty of resources to handle them, along with an inexplicable excess of processor usage. When the window from the game is in focus, process #1 (in task manager) goes to 100% usage, and the game shows signs of minor lag (largely notable when sound effects are repeated in sequence). When the game loses window focus, it continues to draw and update at real time, but the process usage decreases, and the lag disappears.

I have tested this with various games, and the results remain the same, proving that it has nothing to do with my code or code efficiency.

Is this a problem isolated to Xna 3.1, and is there fix for it? Or do I just have to switch to 4.0 and hope my games don't use anything that isn't backwards compatible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

人│生佛魔见 2024-12-09 14:44:50

该问题可能是由于垃圾收集器而发生的。每次垃圾收集器运行时,帧速率可能会下降一两秒,但在 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

The problem may occur because of garbage collector. Everytime garbage collector runs, the frame rate may drop for a second or two, though on Windows it shouldnt be a problem.

Add this line to your code and see how much heap memory is generated. Every time the value goes down, garbage collector is ran.

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

SpriteBatch.DrawInt64 is a SpriteBatch extension which doesnt generate garbage on int, long etc. You can alternatively just use SpriteBatch.DrawString(..., (GC.GetTotalMemory(false) / 1000).ToString(), ... )

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

勿忘心安 2024-12-09 14:44:50

根据我的经验,XNA 在对焦时每秒运行高达 60 帧,在失焦时每秒运行约 20 帧。但是,如果您设置了 IsFixedTimeStep = false;,当进程处于焦点状态时,游戏将尽可能快地运行。在我的机器上,我的游戏运行速度约为 500-700 fps。这与发生的Update()调用的数量有关。所以我的游戏每秒更新500-700次。

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

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

XNA, from my experience, runs up to 60 frames per second while in focus, and at about 20 frames per second when out of focus. IF however, you have set IsFixedTimeStep = false; the game will run as fast as it possibly can when the process is in focus. With my game, on my machine, it runs at about 500-700 fps. This is also tied in to the number of Update() calls that occur. So my game is also updating 500-700 times per second.

My bet is that you have disabled the fixed timestep, and the massive number of Update and Draw calls are consuming 100% of your core and it is messing with your music. I would recommend removing the line IsFixedTimeStep = false; if it's there. If that line does not exist in your code, this is not the problem, although I would bet that your Update or Draw is doing more work than it should be.

Just noticed this in my own game, I have a Console.WriteLine statement (for debugging) in my update loop, this causes lots of lag.

情定在深秋 2024-12-09 14:44:50

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

XNA add a sleep when the window is not in focus!
I solved this problem some time ago overriding Game class and changing the way the Game class understand its form is active or not.

There is not way, as much as i know, to disable this behaviour without modifying Game class behaviour with code.

In particular, the way i found some time ago is a real hack\quirk!
Very unclean solution, but the only way i found.

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 });
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文