XNA粒子系统问题
本文关键字:问题 粒子系统 XNA | 更新日期: 2023-09-27 18:17:38
我一直在制作XNA中的粒子系统,我正在尝试创建两个粒子效果。烟花爆炸和喷泉烟花。
我遇到的问题是,当我在爆炸中添加新粒子时(我做得很快,因为我想让它们同时刷出),帧率会大大下降。
我想知道是否有人能让这更好的解决方案。我看到官方示例使用了队列方法。这对我现在面临的问题有帮助吗?或者它会使程序加载速度变慢,因为它必须在开始时将所有这些粒子加载到队列中?
添加新粒子:
if (isActive)
{
timeSinceLastEmission += gameTime.ElapsedGameTime.Milliseconds;
if (emitterFrequency == 0 || timeSinceLastEmission >= emitterFrequency)
{
emitterFrequency = emissionInterval;
for (int i = 0; i < Math.Round(timeSinceLastEmission / emitterFrequency); i++)
{
if (particleList.Count < MaxParticles)
addParticle();
}
timeSinceLastEmission = 0;
}
}
绘制函数:
public void draw(SpriteBatch spriteBatch)
{
spriteBatch.Begin();
for (int i = 0; i < particleList.Count; i++)
{
spriteBatch.Draw(particleList[i].texture,
particleList[i].position,
null,
particleList[i].color,
particleList[i].rotation,
particleList[i].origin,
particleList[i].textureScale,
SpriteEffects.None,
0);
}
spriteBatch.End();
}
您需要做两件事:
首先,你需要使你的粒子类型为struct
而不是class
。(我猜它是)
class
分配堆内存,并且您的列表将充满对堆上那些对象的引用。每个堆对象都需要由垃圾收集器管理。当你有很多对象时,这是非常慢的。(原因太多,在此不便细述)
struct
将直接位于为列表分配的内存中。运行时可以做一些事情,比如批量分配和清除内存——相当快。你的struct
比参考要大一些,所以尽量让它尽可能的小。你真的需要每个粒子的纹理和原点吗?你可以制造出每粒子系统
(另一个很好的原因是,如果你避免纹理变化,SpriteBatch
要快得多,因为它们需要一个新的批处理-慢)
第二,你应该设置List.Capacity
为你的粒子系统的最大大小
或者,更好的是,您可以使用列表的构造函数来设置起始容量。这将一次性分配列表所需的内存。每当列表达到容量时,它必须分配一个新的更大的列表,并复制其内容。所以,如果你让它足够大,它就不需要重复这个缓慢的操作。
(注意:你会发现你不能在列表的结构中设置单独的成员,就像你可以在类中那样——编译器会给你一个错误。你必须复制出整个结构体,修改它,然后再复制回来。这还不算太糟。但是,如果你愿意,你可以通过使用数组来避免它——但是你必须自己管理大小和容量。
(注2:这个答案中的"慢"与优化粒子系统有关,因为你正在处理大量频繁更新的对象。一般来说,这些操作并不慢。