pixijs-scene-particle-container について
PixiJS 開発者向けに、ParticleContainer で同じテクスチャを共有する軽量パーティクルを大量に描画する方法を解説するスキルです。管理方法、GPU 更新設定、専用コンテナの制約を扱います。
主な機能
- 01共有テクスチャのパーティクルをバッチ描画
- 02パーティクルの作成と一括管理
- 03GPU 属性の動的更新設定
- 04カスタムパーティクルシェーダー
- 05コンテナ単位の色調・透明度・ブレンドモード
活用シーン
- 01多数のスプライトによるパーティクル効果の描画
- 02共有テクスチャを使った弾幕の作成
- 03アニメーション属性の指定による更新の最適化
- 04パーティクル一括の色調変更やフェード
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ pixijs/ pixijs-skills --skill pixijs-scene-particle-containerインストール後、Claude Code で/pixijs-scene-particle-containerを入力して読み込まれたか確認します。
詳細
ParticleContainerは、数百から数万の軽量スプライトを1回の描画呼び出しでレンダリングするための特殊なコンテナです。パーティクルエフェクト、弾幕、またはオブジェクトごとのオーバーヘッドを最小限に抑えながら、多数の似た見た目のオブジェクトを扱う必要がある場合に使用します。パーティクルは単一のベーステクスチャを共有し、使用できるトランスフォームも制限されています。通常のContainerの子ではありません。
pixijs-scene-core-conceptsの知識があることを前提としています。ParticleContainerは別の意味で特殊なリーフです。独自のparticleChildren配列にParticleインスタンスを格納し、通常のPixiJSの子は受け付けません。addChildではなくaddParticleを使用し、他のシーンオブジェクトとグループ化する必要がある場合は、ParticleContainer全体をContainerでラップしてください。
Particle APIはv8で新しく導入されましたが、本番環境で安定して使用できます。
クイックスタート
const texture = await Assets.load("particle.png");
const container = new ParticleContainer({
texture,
boundsArea: new Rectangle(0, 0, app.screen.width, app.screen.height),
dynamicProperties: {
position: true,
rotation: false,
color: false,
},
});
for (let i = 0; i < 10000; i++) {
container.addParticle(
new Particle({
texture,
x: Math.random() * app.screen.width,
y: Math.random() * app.screen.height,
}),
);
}
app.stage.addChild(container);
関連スキル: pixijs-scene-core-concepts(シーングラフの基本)、pixijs-scene-sprite(オブジェクトごとにすべての機能が必要な場合)、pixijs-assets(共有テクスチャ、アトラス)、pixijs-performance(バッチ処理、テクスチャの最適化)、pixijs-scene-container(他の表示オブジェクトと一緒にラップする場合)。
コンストラクターオプション
ParticleContainerOptions
すべてのContainerオプション(position、scale、tint、label、filters、zIndexなど)も使用できます。skills/pixijs-scene-core-concepts/references/constructor-options.mdを参照してください。ただし、childrenは省略されています。代わりにparticlesを使用してください。
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
texture | Texture | null | すべてのパーティクルで共有するベーステクスチャです。省略した場合、コンテナは最初に追加されたパーティクルのテクスチャを使用します。すべてのパーティクルで同じベーステクスチャソースを共有する必要があります。 |
particles | T[] | [] | Particle(またはIParticle)インスタンスの初期配列です。それぞれに対してaddParticleを呼び出す場合と同じですが、呼び出しごとのビュー更新は行われません。 |
dynamicProperties | ParticleProperties | { vertex: false, position: true, rotation: false, uvs: false, color: false } | 各フレームでGPUに再アップロードするパーティクル属性を指定するフラグです。デフォルトで動的なのはpositionのみです。アニメーションさせる属性を指定し、それ以外は速度を優先して静的なままにしてください。 |
roundPixels | boolean | false | パーティクルの位置を最も近いピクセルに丸めます。滑らかなサブピクセル移動と引き換えに、ピクセルアート風のスタイルをよりくっきりとレンダリングできます。 |
shader | Shader | デフォルトのパーティクルシェーダー | デフォルトのパーティクルシェーダーを置き換えます。カスタムシェーダーでは、aPosition、aUV、aColorに加えて、dynamicPropertiesで有効にした動的属性のみを宣言する必要があります。 |
boundsAreaはContainerから継承されますが、ParticleContainerでは実質的に必須です。パフォーマンス上の理由から、コンテナはデフォルトで空の境界((0, 0, 0, 0))を返すため、boundsAreaを設定しないと、カリングが有効な場合に非表示としてカリングされ、containsPointは常に判定に失敗します。
ParticleOptions
Particle は軽量な構造体であり、Container のサブクラスではありません。そのため、ContainerOptions のフィールドは適用されません。オプションの一覧は次のとおりです。
| オプション | 型 | デフォルト | 説明 |
|---|---|---|---|
texture | Texture | — | 必須です。このパーティクルの描画に使用するテクスチャです。同じ ParticleContainer 内のすべてのパーティクルは、同じベーステクスチャソースを共有する必要があります。 |
x | number | 0 | コンテナのローカル空間における X 座標です。 |
y | number | 0 | コンテナのローカル空間における Y 座標です。 |
scaleX | number | 1 | 水平方向のスケール係数です。 |
scaleY | number | 1 | 垂直方向のスケール係数です。 |
anchorX | number | 0 | 0~1 の範囲で指定する水平方向のアンカーです。0 は左、0.5 は中央、1 は右です。 |
anchorY | number | 0 | 0~1 の範囲で指定する垂直方向のアンカーです。0 は上、0.5 は中央、1 は下です。 |
rotation | number | 0 | ラジアン単位の回転角度です。 |
tint | ColorSource | 0xffffff | 16 進数または CSS カラー文字列で指定する色調です。alpha と組み合わせて内部の color フィールドに反映されます。 |
alpha | number | 1 | 透明度(0~1)です。範囲外の値はクランプされます。tint と組み合わせて内部の color フィールドに反映されます。 |
コンストラクターには、単独の引数として Texture を渡すこともできます(new Particle(texture))。これは、上記のデフォルト値を使用する new Particle({ texture }) の省略形です。
Particle.defaultOptions は静的オブジェクトで、再代入するとデフォルト値をグローバルに変更できます。詳しくは、以下の「パーティクルの作成」セクションをご覧ください。
基本パターン
パーティクルの作成
const particle = new Particle({
texture,
x: 100,
y: 200,
scaleX: 0.5,
scaleY: 0.5,
anchorX: 0.5,
anchorY: 0.5,
rotation: Math.PI / 4,
tint: 0xff0000,
alpha: 0.8,
});
container.addParticle(particle);
Particle は、x、y、scaleX、scaleY、anchorX、anchorY、rotation、color、texture という数値フィールドを持つ軽量な構造体です。また、tint(16 進数/CSS カラー)と alpha(0~1)をセッターとして公開し、内部の color フィールドと組み合わせて反映します。変換階層、イベント、フィルターはありません。
単独の引数として Texture を直接渡すこともできます。new Particle(texture) のように指定します。
Particle.defaultOptions を上書きすると、デフォルト値をグローバルに変更できます。
Particle.defaultOptions = {
...Particle.defaultOptions,
anchorX: 0.5,
anchorY: 0.5,
};
particles オプションによる事前設定
const particles = Array.from(
{ length: 10000 },
() =>
new Particle({
texture,
x: Math.random() * 800,
y: Math.random() * 600,
}),
);
const container = new ParticleContainer({
texture,
boundsArea: new Rectangle(0, 0, 800, 600),
particles,
});
コンストラクターに particles を渡す方法は、空のコンテナを作成して各パーティクルに対して addParticle を呼び出す方法と同等ですが、呼び出しごとのビュー更新を回避できます。
動的プロパティと静的プロパティおよび update()
const container = new ParticleContainer({
dynamicProperties: {
rotation: true,
},
});
dynamicProperties は、毎フレーム GPU に再アップロードするパーティクル属性を制御します。ParticleContainer.defaultOptions.dynamicProperties のデフォルト値は次のとおりです。
{ vertex: false, position: true, rotation: false, uvs: false, color: false }
アニメーションさせるプロパティだけを上書きすればよく、それ以外はデフォルト値(position は動的、その他はすべて静的)を引き継ぎます。プロパティは全部で 5 つあります。
vertex:スケール/アンカーポイントの頂点position:位置rotation:回転uvs:テクスチャ座標(フレームを切り替えるパーティクル用)color:色調とアルファ
アニメーションさせるプロパティだけを動的に設定してください。静的プロパティのほうが処理コストを抑えられます。実行時に静的プロパティを変更した場合は、再アップロードするために container.update() を呼び出してください。
container.particleChildren.forEach((p) => {
p.tint = 0x00ff00;
});
container.update();
particleChildren の一括操作
// Bulk add
const batch = [];
for (let i = 0; i < 5000; i++) {
batch.push(
new Particle({ texture, x: Math.random() * 800, y: Math.random() * 600 }),
);
}
container.particleChildren.push(...batch);
container.update();
// Bulk remove
container.particleChildren.length = 0;
container.update();
addParticle、addParticleAt、removeParticle、removeParticleAt、removeParticles は、呼び出すたびにビューを更新します。大量の一括操作では、配列を直接操作してから update() を 1 回だけ呼び出すほうが高速です。
テクスチャとシェーダーのオプション
ParticleContainerOptions の texture は省略可能です。省略した場合、コンテナは追加された最初のパーティクルのテクスチャを使用します。それ以降のすべてのパーティクルは、同じベーステクスチャソースを共有する必要があります。アトラスをあらかじめ指定したい場合や、実行中に最初のパーティクルが変わる可能性がある場合は、明示的に設定してください。
const container = new ParticleContainer({ texture });
shader を使うと、デフォルトのパーティクルシェーダーを任意の Shader インスタンスに置き換えられます。カスタムシェーダーでは、パーティクルパイプがアップロードする属性(aPosition、aUV、aColor と、dynamicProperties で有効にした動的属性)を宣言する必要があります。カスタムのブレンディング計算、距離フィールドスプライト、標準以外のエフェクトに使用できます。
const container = new ParticleContainer({ texture, shader: myCustomShader });
パーティクルシステム全体のフェードまたは色調変更
const burst = new ParticleContainer({ texture, particles });
const layer = new Container();
layer.addChild(burst);
app.ticker.add(() => {
layer.alpha -= 0.01; // fades every particle
});
burst.tint = 0x66ccff; // tints every particle
コンテナの alpha、tint、blendMode は、スプライトの場合と同じようにパーティクルへ適用されます。そのため、particleChildren に触れずにシステム全体をフェードしたり、色を変更したりできます。
制限事項
ParticleContainer は速度を優先するため、意図的に機能を制限しています。
- フィルター、マスク、パーティクルごとのブレンドモードには対応していません。ブレンドモードはコンテナレベルで適用されます。
ParticleContainerにblendModeを設定するか、親のContainerから継承させてください(デフォルトの"inherit"は、SpriteやMeshと同様に、祖先のブレンドモードを適用します)。パーティクルのバッチ全体で、ブレンドモードは 1 つだけ共有されます。コンテナまたは祖先のalphaとtintは、各パーティクル自身のalpha/tintに加えて、すべてのパーティクルに乗算されます。 - パーティクルに子をネストできません。
- 境界を自動計算しません。
- すべてのパーティクルが同じベーステクスチャソースを共有する必要があります(アトラスは使用できますが、互いに無関係な複数のテクスチャは使用できません)。
shaderオプションを使ったカスタムシェーダーに対応しています。
コンテナメソッドの移行
ParticleContainer は、GPU バッファーの更新に最適化された独自の子管理 API を使用します。標準の Container 子メソッドを ParticleContainer で呼び出すと、エラーがスローされます。
| 標準の Container メソッド | ParticleContainer の同等メソッド |
|---|---|
addChild(child) | addParticle(particle) |
removeChild(child) | removeParticle(particle) |
addChildAt(child, index) | addParticleAt(particle, index) |
removeChildAt(index) | removeParticleAt(index) |
removeChildren(begin, end) | removeParticles(begin, end) |
getChildAt(index) | container.particleChildren[index] に直接アクセス |
swapChildren() | 使用できません |
reparentChild() | 使用できません |
よくある間違い
[CRITICAL] ParticleContainer への Sprite の追加
誤り:
const container = new ParticleContainer();
const sprite = new Sprite(texture);
container.addChild(sprite);
正しい例:
const container = new ParticleContainer();
const particle = new Particle(texture);
container.addParticle(particle);
ParticleContainer は Sprite の子要素を受け付けません。addChild を呼び出すとエラーが発生します。パーティクルは Particle インスタンス(または IParticle を実装する任意のオブジェクト)である必要があり、addParticle を使って追加します。これは、ParticleContainer が Sprite の子要素を受け付けていた v7 からの全面的な改修です。
[HIGH] ParticleContainer に boundsArea を設定しない
誤り:
const container = new ParticleContainer();
// bounds is always (0, 0, 0, 0) — culling and hit testing fail
正しい例:
const container = new ParticleContainer({
boundsArea: new Rectangle(0, 0, 800, 600),
});
パフォーマンスのため、ParticleContainer はデフォルトで空の境界 (0, 0, 0, 0) を返します。boundsArea を設定しないと、カリングが有効な場合にコンテナが非表示としてカリングされ、containsPoint は常にヒットしません。パーティクルが占める領域を boundsArea に設定してください。
[HIGH] particleChildren の代わりに children を使用する
誤り:
container.addParticle(new Particle(texture));
console.log(container.children.length); // 0
正しい例:
container.addParticle(new Particle(texture));
console.log(container.particleChildren.length); // 1
パーティクルは children ではなく、particleChildren 配列に格納されます。ParticleContainer では標準の Container.children 配列は空です。パーティクルの列挙、カウント、操作には、particleChildren と *Particle メソッドを使用してください。
[MEDIUM] ParticleContainer を通常のコンテナとして使用しない
ParticleContainer が含むのはパーティクルであり、表示オブジェクトではありません。パーティクルシステムを背景のスプライトや UI オーバーレイとまとめる必要がある場合は、通常の Container の中に ParticleContainer 自体を配置します:
const world = new Container();
world.addChild(backgroundSprite, particleContainer, uiLayer);