$npx -y skills add pixijs/pixijs-skills --skill pixijs-scene-particle-containerUse this skill when rendering thousands of lightweight sprites in PixiJS v8. Covers ParticleContainer with Particle instances, addParticle/removeParticle, particleChildren array, dynamicProperties (vertex, position, rotation, uvs, color), boundsArea, roundPixels, update. Triggers
| 1 | `ParticleContainer` is a specialized container for rendering hundreds to tens of thousands of lightweight sprites in a single draw call. Use it for particle effects, bullet patterns, or any case where you need a large number of similar-looking objects with minimal per-object overhead. Particles share a single base texture and have a restricted transform set; they are not full `Container` children. |
| 2 | |
| 3 | Assumes familiarity with `pixijs-scene-core-concepts`. `ParticleContainer` is a special leaf in a different sense: it contains `Particle` instances in its own `particleChildren` array and rejects normal PixiJS children. Use `addParticle`, not `addChild`, and wrap the whole `ParticleContainer` in a `Container` if you need to group it with other scene objects. |
| 4 | |
| 5 | The Particle API is new in v8 but is stable for production use. |
| 6 | |
| 7 | ## Quick Start |
| 8 | |
| 9 | ```ts |
| 10 | const texture = await Assets.load("particle.png"); |
| 11 | |
| 12 | const container = new ParticleContainer({ |
| 13 | texture, |
| 14 | boundsArea: new Rectangle(0, 0, app.screen.width, app.screen.height), |
| 15 | dynamicProperties: { |
| 16 | position: true, |
| 17 | rotation: false, |
| 18 | color: false, |
| 19 | }, |
| 20 | }); |
| 21 | |
| 22 | for (let i = 0; i < 10000; i++) { |
| 23 | container.addParticle( |
| 24 | new Particle({ |
| 25 | texture, |
| 26 | x: Math.random() * app.screen.width, |
| 27 | y: Math.random() * app.screen.height, |
| 28 | }), |
| 29 | ); |
| 30 | } |
| 31 | |
| 32 | app.stage.addChild(container); |
| 33 | ``` |
| 34 | |
| 35 | **Related skills:** `pixijs-scene-core-concepts` (scene graph basics), `pixijs-scene-sprite` (when you need full features per object), `pixijs-assets` (shared textures, atlases), `pixijs-performance` (batching, texture optimization), `pixijs-scene-container` (wrap with other display objects). |
| 36 | |
| 37 | ## Constructor options |
| 38 | |
| 39 | ### ParticleContainerOptions |
| 40 | |
| 41 | All `Container` options (`position`, `scale`, `tint`, `label`, `filters`, `zIndex`, etc.) are also valid here — see `skills/pixijs-scene-core-concepts/references/constructor-options.md`. Note that `children` is omitted: use `particles` instead. |
| 42 | |
| 43 | | Option | Type | Default | Description | |
| 44 | | ------------------- | -------------------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 45 | | `texture` | `Texture` | `null` | Shared base texture for all particles. If omitted, the container falls back to the texture of the first particle added; every particle must share the same base texture source. | |
| 46 | | `particles` | `T[]` | `[]` | Initial array of `Particle` (or `IParticle`) instances. Equivalent to calling `addParticle` for each, but skips per-call view updates. | |
| 47 | | `dynamicProperties` | `ParticleProperties` | `{ vertex: false, position: true, rotation: false, uvs: false, color: false }` | Flags for which particle attributes re-upload to the GPU every frame. Only `position` is dynamic by default; mark what you animate, leave the rest static for speed. | |
| 48 | | `roundPixels` | `boolean` | `false` | Rounds particle positions to the nearest pixel. Produces crisper rendering for pixel-art styles at the cost of smooth sub-pixel motion. | |
| 49 | | `shader` | `Shader` | default particle shader | Replaces the default particle shader. The custom shader must declare `aPosition`, `aUV`, `aColor`, plus any dynamic-only attributes enabled via `dynamicProperties`. | |
| 50 | |
| 51 | `boundsArea` is inherited from `Container` but is effectively required on `ParticleContainer`: the container returns empty bounds `(0, 0, 0, 0)` by default for performance, so without `boundsArea` it is culled as invisible when culling is active and `containsPoint` always misses. |
| 52 | |
| 53 | ### ParticleOptions |
| 54 | |
| 55 | `Particle` is a lightweight struct, not a `Container` subclass |