c# - 如何在 C# 中有效地处理许多更新对象?

标签 c# garbage-collection xna

我正在使用 C# 和 XNA 开发 2D 高空射击游戏。我有一个我称之为“子弹”的类,需要每隔几分之一秒更新其中的许多实例。

我执行此操作的第一种方法是拥有一个通用项目符号列表,并根据需要简单地删除和添加新项目符号。但是在这样做的过程中,GC 经常启动,我的游戏有一些周期性的不稳定滞后。 (删掉了很多代码,只是想展示一个简单的片段)

if (triggerButton)
{
    bullets.Add(new bullet());
}
if (bulletDestroyed)
{
    bullets.Remove(bullet);
}

我的第二个也是当前的尝试是拥有一个单独的通用项目符号堆栈,当我用完一颗子弹时我将其插入,并在我需要新子弹时弹出一颗子弹(如果堆栈中有任何东西)。如果堆栈中没有任何内容,那么我会向列表中添加一个新项目符号。它似乎减少了抖动延迟,但话又说回来,有时仍然会出现一些抖动延迟(虽然我不知道这是否相关)。

if (triggerButton)
{
    if (bulletStack.Count > 0)
    {
        bullet temp = bulletStack.Pop();
        temp.resetPosition();
        bullets.Add(temp);
    }
    else
    {
        bullets.Add(new bullet());
    }
}
if (bulletDestroyed)
{
    bulletStack.Push(bullet);
    bullets.Remove(bullet);
}

所以,我知道过早的优化是万恶之源,但这是非常明显的低效率,我可以及早发现(这甚至不必担心敌人的子弹会填满屏幕)。所以我的问题是:将未使用的对象推送到堆栈会调用垃圾收集吗?引用会保持事件状态还是对象仍在被销毁?有没有更好的方法来处理更新许多不同的对象?例如,我是不是太花哨了?只遍历列表并以这种方式找到未使用的项目符号是否可以?

最佳答案

这里有很多问题,很难说。

首先是 bullet结构还是类?如果 bullet 是一个类,那么任何时候您构造一个类,然后取消它的根(让它超出范围或将其设置为 null),您将添加 GC 需要收集的东西。

如果你要制作很多这样的东西,并且每一帧都更新它们,你可能需要考虑使用 List<bullet>bullet作为一个结构,并且 List 被预先分配(生成它的大小足以容纳所有项目符号,因此它不会在您调用 List.Add 时重新创建)。这将极大地帮助减轻 GC 压力。

另外,只是因为我需要咆哮:

So, I know premature optimization is the root of all evil, but this was very noticeable inefficiency

永远不要害怕优化您知道会导致问题的例程。如果您看到性能问题(即:您的滞后),这不再是过早的优化。是的,您不想优化每一行代码,但您确实需要优化代码,尤其是当您发现真正的性能问题时。一发现问题就立即优化比稍后尝试优化要容易得多,因为在添加大量使用 bullet 的其他代码之前,所需的任何设计更改都将更容易实现。类。

关于c# - 如何在 C# 中有效地处理许多更新对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2335883/

相关文章:

c# - 以编程方式确定是否启用了 Windows 8 安全启动

c# - 我如何才能发现第 0 代堆中有哪些可终结对象?

c# - 如何在 XNA 中为绘制的线条添加 Z 深度透视图?

c# - 在 XNA 中显示不同的屏幕?

c# - 查找值在数组中的位置

c# - 查找元素是否确认页面已完全加载?

c# - 在本地使用 SQL Server CE 并首先在生产 Entity Framework 代码上使用 SQL Server 2008?

java - 关闭 java InputStream 后内存未释放

c++ - 我必须 munmap() 一个 mmap() 文件吗?

c# - 无法在 XNA4 中加载 spriteFont