弾が着弾して火花が飛び散るような、複雑な連鎖演出(Sub-emitter)をGPUパーティクルで完璧に動作させる接続フローです。

不具合 of 症状と具体的な現象

Visual Effect Graph(VFX Graph)で、親パーティクルが消滅した瞬間(Dieイベント)に子パーティクルを発生させる「Sub-emitter」を構築した際、以下の問題が頻発します。

  • 親は正常に消滅しているが、子パーティクルが1つも生成されない。
  • VFX Graph内でエラーは出ておらず接続も正しいように見えるが、実行時に何も描画されない。
  • 親の生成数が少ないうちは子が出るが、親が大量になると子が突然出なくなる。

初心者向けの例え話:カプセルトイと極小のトレイ

この現象を理解するために、親パーティクルを「親カプセル」、子パーティクルを「中に入っている大量のミニおもちゃ」に例えてみましょう。

親カプセルが割れた(消滅した)瞬間に、中から大量のミニおもちゃを飛び出させて、床に並べたいと考えています。しかし、ここには2つの重大なルールがあります。

1つ目のルールは、「おもちゃを並べる専用トレイ(子パーティクルのCapacityバッファメモリ)を事前に用意すること」です。もしトレイが極端に小さく、3個しか乗らない場合、カプセルが割れて100個のおもちゃが飛び出そうとしても、トレイに乗り切らない残り97個は置く場所がなくて消滅してしまいます。これが Capacity不足 の状態です。GPUはメモリを事前に固定で確保するため、後からトレイを大きくしてくれません。

2つ目のルールは、「カプセルが割れた!」という手紙(Dieイベント)を伝える経路です。親から手紙を書いて直接おもちゃ(Initialize)に渡そうとしても、間にある受付窓口(Spawnコンテキスト)を通さないと、おもちゃたちはいつ発生すればいいのかわかりません。手紙が窓口で止まっている状態が、Spawnコンテキストの接続ミス です。

想定される主な原因

VFX GraphにおけるSub-emitterがスポーンしない原因は、主に以下の3点です。

  1. 子システム側のCapacity(容量)が小さい: GPUパーティクルは実行中に動的にメモリを確保できません。最大メモリ(Capacity)を初期化時に固定確保するため、この値がデフォルト(64など)のままだと、親が一度に消滅した瞬間にバッファが枯渇し、スポーン処理がGPUによって無視されます。
  2. イベント接続のフロー間違い: 親の `Trigger Event On Die` ノードから出力されたイベントを、子システムの `Initialize` に直接接続している場合です。イベントは必ず `Spawn (GPU)` コンテキストを経由して `Initialize` に伝わる必要があります。
  3. 境界ボックス(Bounds)のカリング: VFX全体の境界判定サイズが不適切な場合、カメラの視界から外れたと判定されて描画がカリングされます。

具体的な解決方法と手順

Sub-emitterを正常に動作させるための設定フローです。

手順1:Capacity の拡張(最重要)

子パーティクル側の Initialize コンテキストを選択し、インスペクターにある **`Capacity`** をデフォルトの低い値から **`2000` 〜 `3000`** 程度に引き上げてください。これは、親が消滅した際に発生する「子パーティクルの最大同時存在数」をカバーするのに十分な大きさである必要があります。

手順2:GPU Spawn コンテキストの経由とノード接続

親の消滅イベントを伝える正しい接続フローを再構築します。

  • 親のシステム内に `Trigger Event On Die` ノードを配置します。
  • 子システムの開始点として、通常の `Spawn` ではなく **`Spawn (GPU)`** コンテキストを配置します。
  • `Trigger Event On Die` の出力(Event)から、`Spawn (GPU)` の `Start` 入力へ接続します。
  • `Spawn (GPU)` の出力から、子システムの `Initialize` コンテキストの `Spawn` 入力へ接続します。

手順3:データの継承(Inherit)設定

子システムの内側で `Inherit Source Position` および `Inherit Source Velocity` ノードを配置し、親から引き継いだ座標からパーティクルが放出されるように設定します。これにより、移動中に親が死んだ場合でも、その場から自然に子パーティクルが散らばるようになります。

実務向けチェックリスト&トラブルシューティング

チェック対象 確認項目 対策・推奨設定
子システムのCapacity デフォルト値(64等)のままか? 同時発生数に応じて2000以上に増やす。
接続コンテキスト Spawn (GPU) を経由しているか? Spawn (GPU) を中間に配置して接続する。
インヘリット設定 親の位置を引き継いでいるか? `Inherit Source Position` を使用する。

以下は、C#スクリプトからVFX Graphのカスタムイベントをトリガーし、子エフェクトの動作を確認するためのサンプルコードです。

using UnityEngine;
using UnityEngine.VFX;

[RequireComponent(typeof(VisualEffect))]
public class VFXSubEmitterDebugger : MonoBehaviour
{
    private VisualEffect vfxComponent;
    [SerializeField] private string customEventName = "OnParentDieTest";

    void Start()
    {
        vfxComponent = GetComponent<VisualEffect>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space) && vfxComponent != null)
        {
            VFXEventAttribute eventAttribute = vfxComponent.CreateVFXEventAttribute();
            eventAttribute.SetVector3("position", transform.position);
            vfxComponent.SendEvent(customEventName, eventAttribute);
            Debug.Log($"Sent Event: {customEventName}");
        }
    }
}

このデバッグスクリプトを使用することで、ゲーム実行中にVFX GraphのSub-emitterが正しくイベントを受け取ってスポーンするかどうかを、親システム全体の動作を待たずに単体でテスト可能です。プロファイラを確認しながらCapacityの閾値を最適化する際にも有効です。