Best way to spawn a lot of moving sprites/particles?

Hi guys I’m new to Defold and the first thing I’d like to do with a new engine is spawning a lot of moving sprites/particles.

What I’ve currently done is modded the ‘Getting started tutorial’ so instead of spawning platforms it spawns white particles (10px x 10px). Well the problem is as soon as it hits like 1000 particles i get this error:

ERROR:GAMEOBJECT: Could not create script component, out of resources.
ERROR:GAMEOBJECT: Could not spawn an instance of prototype /level/white_particle.goc.
ERROR:GAMEOBJECT: Instance ‘/instance1032’ could not be found when dispatching message ‘set_speed’ sent from main:/level/controller#script

I already fiddled with the project settings but no luck. So my guess is that I’m doing it wrong.

I’m used to use things like a SpriteBatch for rendering a lot of sprites.

I hope someone can explain me how to spawn a lot of moving sprites/particles. Btw I don’t want to use the particle FX, i want to do it custom.

Thanks!

1 Like

Related to this? max_instances is effectively capped at 1025

Does each game object have a script?

3 Likes

Thanks, now I have deleted the script file i can spawn as many sprites as i want.

BUT when i spawn like 3000 sprites the framerate drops massively.

So is there a way of spawning a lot of sprites while still maintaining 60fps?

Thanks!

2 Likes

I’m relatively new to Defold, but I’d guess that there probably isn’t. Try enabling the profiler:

msg.post("@system:", “toggle_profile”, {})

The profiler will display time consumption by different processes to give you an idea of what’s creating the framerate drop. I have a game that uses sprite objects for tile-based rooms instead of tilemaps for certain reasons, and I can’t maintain 60 fps when two rooms are present because the player is transitioning between them. In my case, what was taking a large amount of time was the ‘game object’ process - not a particular script, just the general processing required for game objects. This processing is a little more costly than you might first expect - sprites have to render in a very specific order which requires some sorting in order for transparency to work properly, which can be costly. It would be nice if something like this could be done with tons of game objects, but I think you might want/need to use the built-in FX system. Depending on how you’re arranging particles, you could also have sprites with several particles spread in a random pattern and use a couple hundred of those instead of a couple thousand lone sprites if you can make that work for your purposes.

Good luck!

2 Likes

Thanks for your reply Lukas! The processing is not the problem in my case, I render 3000 sprites all at once and after that the game starts. And during gameplay i have a low framerate, so that’s after the rendering of the sprites.

I’ll have a look at the particle FX and see if i can use it for my case.

Meanwhile if someone has a suggestion to improve performance on rendering this amount of sprites I’m happy to hear!

2 Likes

Hold on, what exactly do you mean by this? Are the sprites still present on the screen after the start of the game?

2 Likes

Well yes but this is just for testing purposes.

What i like to achieve is a particle explosion of say 3000 sprites/particles. So when the user presses ‘fire’ there will be an explosion of 3000 particles. I know 3000 particles is ‘a lot’ but i’m just testing the limits of Defold.

I come from a JS background where i can render 3000 particles without a problem, even 50.000 particles is possible.

1 Like

Yes, that makes sense in JS. Were you using pure WebGL? If so, then nothing is sorting the z-values of all of your triangles unless you specifically write or borrow a utility to do so. If you’ve written something to do that yourself, you might be familiar with how much of a nightmare that can be, especially when using an interpreted language which doesn’t always have the performance of something like C.

As far as ‘rendering’, the sprites have to be rendered each frame, rendering isn’t a one-time process. Even if you aren’t making any changes to which sprite the particles are using, they still have to be rendered each frame. If it’s possible, do you think you could share a screenshot of a running build with the visual profiler enabled? That could help shed some light on this issue.

2 Likes

Yes i used WebGL with the Pixi.js library.

Here is a screenshot with the profiler enabled.

Thanks!

1 Like

I have been playing with the particle FX and it’s amazing! Now i can create a parallax background by layering multiple instances of the FX and this will also work for a explosion!

So this solved all my problems, i guess it’s just a no go to accomplish this with regular sprites?

4 Likes

For the kind of thing you’re describing it sounds as if particle effects using the ParticlFX component is a much better choice. A game object comes with a bit of a cost. A game object has a transform that needs to be updated every frame, the same goes for a sprite. As you can see from your screenshot you spend a lot of time updating transforms.

On the other hand, this demo is made using Defold: https://www.youtube.com/watch?v=Mptu8h-qFL8

@Ragnar_Svensson could you please tell us how the Pixel Demo was made?

6 Likes

We really need to improve sprite perf, it has been decreasing a bit over the years. I had a quick glance at the offending part, and a quick guess is that some of the cost comes from when we switched over to non-uniform scaling in the engine. The new code is a little sloppy for the sprites. We made the pixel demo before this and then we had no perf issues with >4000 game objects, each with a sprite and collision object. Lua is directing the animation of the “pixels” (all done through go.animate, except for when physics take over). I’ll add an issue for this.
As @Lukas_Palmer pointed out, a sprite is much more expensive relative to particles, but it still shouldn’t be that expensive.

3 Likes

@Ragnar_Svensson, do you think that this issue might be able to be fixed by the next Defold release, presumably 1.2.79?

1 Like

Unfortunately not, right now the whole team is focusing on HTML5 issues. It’s a fairly limited task though so hopefully we can squeeze it in further down the line.

2 Likes

We have done a bit of investigation into sprite perf. One thing that really improved on desktop was to actually use the -O2 flag (compiler optimisations) when compiling. @britzl made a test in the optimised binary with 32000 sprites that ran fine (on desktop), where each sprite was also animated. We have avoided that flag historically because without it, we programmers have to be on our toes (desktop is such a lazy environment to code in :wink:). There is also some optimisations we can do in the sprite-transform code that would surely bring down the computations a bit, but the actual effect has yet to be seen when measuring.
Bottom line anyway is that perf is actually fine on desktop, it just hasn’t been shipped yet, so to speak.

I submitted a pull request for this. It should hopefully end up in the next version.

4 Likes

Thank you! Hopefully this gets included in 1.2.80!

1 Like

It is worth mentioning that 32000 moving sprites were achieved using go.animate() and not through procedural animation in update(). Procedural animation using Lua will result in script execution becoming the bottleneck long before you reach 32000 GOs.

2 Likes

Yeah, I don’t doubt that procedural animation through scripts would be a nightmare. ~32000 * 60 is a lot. Luckily for my purposes I won’t need to procedurally animate a ton of sprites, let alone 32000. I just need a couple thousand sprites to act as something similar to a tilemap.