This explanation is currently available in Japanese.
ひとことで
粒子の誕生・移動中・衝突・消滅といったイベントを合図に、別の粒子の放出を始める仕組みです。親の粒子が消えるときに子の粒子が生まれ、子が消えるときに孫が生まれる、という連鎖で、打ち上げ花火や着弾の火花のような多段階のエフェクトを 1 つのシステムで組み立てられます。
ゲームでの使いどころ
- 花火:上昇する玉(親)が尾を引き(移動中イベント)、頂点で消えると星が開き(消滅イベント)、星が消えるとパチパチと光る(孫)。
- 着弾・衝突:弾の粒子が壁に当たった瞬間に火花と破片を出す(衝突イベント)。
- 雨・水滴:雨粒が地面に当たると、小さな水しぶきが跳ねる。
- 魔法:飛んでいく光の玉が、通過した場所に小さな光を残していく。
しくみ
各粒子は、状態(位置・速度・年齢など)に加えて、どのイベントでどの子エミッターを起動するかという設定を持ちます。
| イベント | 起動のタイミング | 子に引き継ぐもの |
|---|---|---|
| 誕生(Birth) | 親が生まれた瞬間 | 位置 |
| 移動中(Update / Trail) | 毎フレーム、または一定距離ごと | 位置、速度の一部 |
| 衝突(Collision) | 物体に当たった瞬間 | 位置、衝突面の法線、反射した速度 |
| 消滅(Death) | 寿命が尽きた瞬間 | 位置、速度、色 |
子の粒子は、親の位置から放出され、必要に応じて親の速度や色を継承します。花火の星が放射状に広がるのは、子の速度を「親の速度 + 球面上のランダムな方向 × 初速」にしているからです。
処理としては、粒子の更新ループの中で「イベントが起きた粒子」を集め、そこから新しい粒子を同じ(または別の)プールに追加するだけです。
実装のポイント
- プールを使う:子の粒子を生成のたびに new すると、ガベージコレクションで引っかかります。固定長の配列をオブジェクトプールとして使い回します(デモも 5000 個のリングバッファです)。
- 上限を決める:連鎖は爆発的に数が増えます。1 イベントあたりの子の数と、全体の最大数に上限を設けます。
- GPU パーティクルでは:イベントを GPU 上で扱うには、イベントを追記するバッファ(Append Buffer)と、次のフレームでそれを読み出す仕組みが必要です。Niagara の Event Handler や VFX Graph の GPU Event がこれにあたります。
つまずきやすい点
- 同じフレームで生まれた子の更新:更新ループの途中で追加した子を、同じフレームでもう一度更新してしまうと、子だけ 1 フレーム先に進みます。追加分はループの後で処理するか、年齢 0 のまま扱います。
- イベントの取りこぼし:衝突イベントは、1 フレームで壁を通り抜ける高速な粒子だと検出できません。
- 見た目の過剰:連鎖を重ねすぎると画面が粒子で埋まり、何が起きたか分かりにくくなります。
デモで試すこと
- 3 つのイベント(尾・開花・パチパチ)をそれぞれオフにして、花火のどの部分がどのイベントから生まれているかを確かめてください。
- 「開花」をオフにすると、玉は上昇して消えるだけになります。サブエミッターがなければ、1 つのエミッターでは開花を作れないことが分かります。
- 左下の「発生したイベント」の数は、親の消滅や星の消滅で子の放出が起動した回数です。