我正在使用 C# 和 XNA 开发 2D 头顶射击游戏。我有一个类,我将其称为“bullet”,并且需要每隔几分之一秒更新其中许多实例。
我的第一个方法是拥有一个通用的项目符号列表,然后根据需要简单地删除和添加新的项目符号。但在这样做的过程中,GC 经常启动,我的游戏会出现一些周期性的不稳定滞后。 (删去了很多代码,但只是想展示一个简单的片段)
if (triggerButton)
{
bullets.Add(new bullet());
}
if (bulletDestroyed)
{
bullets.Remove(bullet);
}
我的第二次也是当前的尝试是拥有一个单独的通用子弹堆栈,当我用完一颗子弹时,我会将其推入其中,并在我需要新子弹时弹出一颗子弹(如果堆栈中有任何东西)。如果堆栈中没有任何内容,那么我会向列表中添加一个新项目符号。它seems减少生涩的滞后,但话又说回来,有时仍然会出现一些生涩的滞后(尽管我不知道这是否相关)。
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 是一个类,则任何时候您构造一个类,然后取消它的根(让它超出范围或将其设置为空),您都将添加 GC 需要收集的内容。
如果您要制作其中许多内容,并每帧更新它们,您可能需要考虑使用List<bullet>
with bullet
是一个结构,并且列表是预先分配的(生成的大小足以容纳所有项目符号,因此在您调用时不会重新创建它List.Add
)。这将极大地缓解 GC 压力。
另外,因为我需要咆哮:
所以,我知道过早的优化是万恶之源,但这是非常明显的低效率
永远,永远,不要害怕优化例行公事你知道这会造成问题。如果您发现性能问题(即:滞后),这不再是过早的优化。是的,您不想优化每一行代码,但是您确实需要优化代码,尤其是当您看到真正的性能问题时。一旦发现问题就对其进行优化比稍后尝试优化要容易得多,因为在添加大量使用您的其他代码之前,所需的任何设计更改都将更容易实现。bullet
class.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)