As a Roblox developer, it is currently too hard to rely on particle emitters widely, even for simple static particles, because they perform poorly compared to alternatives.
If Roblox is able to address this issue, it would improve my development experience because it would allow me to utilize particle emitters in more places without making performance sacrifices.
This post is probably overly long, it can more or less be summarized as “billboards seem to perform hundreds of times better than particles and that seems a bit much.”
Relevantly, compared to other engines & games, Roblox particle emitters also appear to across the board perform worse in practice. I didn’t get specific numbers on this or do concrete tests though, it’s mostly just based on anecdotal observations and ballpark numbers, and it all makes me believe that there is maybe something going on with Roblox’s particles specifically that is unusual.
Details, tests, & Comparisons
The problem
Currently, ParticleEmitter
s perform unexpectedly poorly based on a bit of rough empirical testing.
Emitting only a few hundred static particles at the same time (no animations, just permanent or semi-permanent particles emulating the behaviour of a BillboardGui
) can bring client performance to a crawl (<1 FPS) on mid-tier hardware.
On other hardware, just asking for information from a variety of players, the observed difference in framerates was sometimes even larger than I observed on my hardware. Further, the range that the particles can be viewed at is incredibly small compared to alternatives which perform substantially better even on decent hardware, which makes them even less ideal for a lot of use cases.
What might be going wrong?
I believe based on somewhat weak evidence that this is a consequence of overdraw on the GPU, e.g. possibly due to particle draws not being z-sorted like billboards and resulting in lots of redraws and recomputations, but this is a guess mostly based on how extreme the observed difference in performance is between particles and billboards and I don’t have clear direct evidence of this being the case.
What are my expectations & why do I think something is wrong?
My expectations are that BillboardGui
s and ParticleEmitter
s should behave and perform roughly the same in practice, and I would put a loose expectation that particles could reasonably perform maybe 10-20x worse in a less-than-ideal scenario, but not 100-200x worse on mid-tier hardware as I observe below. This is just based on the work that I believe particle emitters may have to do, and based on the assumption that that work would perform better or equivalently compared to a luau implementation.
I believe that the extreme difference is an indicator of a problem in the particle implementation rather than a true limitation in the implementation (e.g. I don’t think it’s things like lighting computations being that much more expensive, or things like skewing playing a major role)
Comparison between BillboardGuis & ParticleEmitters
The numbers below are pretty rough estimates. The tests I did involved spawning coin images around a point, each being an equivalent size of 1x1 studs in world space. These were done with a Ryzen 3 3200G CPU (an okay mid-tier CPU released in 2019) and an AMD RX 570 (decent mid-tier card released in 2017 capable of rendering most Roblox games above 240 FPS) on a Windows 10 machine.
For the billboard test I used invisible & non-collideable 1x1x1 spheres to contain billboard GUIs, cloning and pivoting the pre-prepared spheres into position.
For the ParticleEmitter
test I did the same, but instead of cloning, I set the lifetime of the particles to a large value, set the rate to 0, moved the sphere into position, and called :Emit()
to create a particle. I repeated the test with a version where I cloned the sphere to make sure that there was no degradation from using a single ParticleEmitter
instance and didn’t observe any change in performance between the two particle tests. I additionally did tests to see if I could identify any effect from the Rate being 0 or the lifetime being large and also didn’t observe any differences in that case either.
BillboardGui results
BillboardGui
s with a single ImageLabel
appear to perform substantially better (in the range of 100-200x) when compared to static particle emitters despite appearing identical. Even when implementing luau code to update the locations of billboards in the world every frame with math similar to the math that would be implemented for particles does not make a significant performance impact when compared to ParticleEmitter
s.
ParticleEmitter results
My system was able to handle approximately 30k billboard GUIs on screen before hitting 30 FPS. When emitting static particles from an emitter using :Emit()
and doing no additional work it took roughly only 200-300 particles to bring system performance below 10 FPS, quickly reaching unplayable sub-1 framerates.