This is a connection flow that perfectly works with GPU particles to create a complex chain effect (Sub-emitter), such as a bullet landing and sparks flying.
Problems of symptoms and specific phenomena
When building a "Sub-emitter" that generates child particles at the moment the parent particle disappears (Die event) in Visual Effect Graph (VFX Graph), the following problem frequently occurs.
- The parent disappears normally, but no child particles are generated.
- There are no errors in the VFX Graph and the connections seem correct, but nothing is drawn at runtime.
- Children will appear while the number of parents produced is small, but when a large number of parents are created, children suddenly stop appearing.
An analogy for beginners: Capsule toys and tiny trays
To understand this phenomenon, let's compare the parent particle to a "parent capsule" and the child particles to "a bunch of mini toys inside."
At the moment the parent capsule breaks (disappears), I want to pop out a large number of mini toys from inside and arrange them on the floor. But there are two important rules here.
The first rule is to "prepare in advance a special tray (capacity buffer memory for child particles) for arranging toys." If the tray is extremely small and only 3 toys can fit on it, even if the capsule breaks and 100 toys are about to fly out, the remaining 97 toys that cannot fit on the tray will disappear because there is no place to put them. This is a Capacity Insufficient condition. The GPU reserves a fixed amount of memory in advance, so the tray cannot be enlarged later.
The second rule is the path to convey the letter "The capsule has broken!" (Die event). Even if you write a letter from a parent and try to give it directly to the toys (Initialize), the toys won't know when to spawn unless it goes through the reception desk (Spawn context) in between. If the letter is stuck at the counter, this is a Spawn context connection error.
Assumed main causes
There are three main reasons why Sub-emitters do not spawn in VFX Graph:
- Low Capacity on child system: GPU particles cannot dynamically allocate memory during execution. The maximum memory (Capacity) is fixed and secured at the time of initialization, so if this value is left at the default (such as 64), the buffer will be exhausted the moment the parents disappear all at once, and the spawn process will be ignored by the GPU.
- Incorrect event connection flow: This is when the event output from the parent's `Trigger Event On Die` node is directly connected to the child system's `Initialize`. Events must always be propagated to `Initialize` via the `Spawn (GPU)` context.
- Bounds Culling: If the bounds size of the entire VFX is inappropriate, the drawing will be culled as it is judged to be out of the camera's field of view.
Specific solutions and procedures
This is the configuration flow for making Sub-emitter work properly.
Step 1: Expand Capacity (Most Important)
Select the Initialize context on the child particle side and increase **`Capacity`** in the inspector from the default low value to around **`2000` ~ `3000`**. This must be large enough to cover the maximum number of concurrent child particles that occur when the parent dies.
Step 2: Via GPU Spawn context and connect to node
Rebuild the correct connection flow to convey parent death events.
- Place a `Trigger Event On Die` node within the parent system.
- Place a **`Spawn (GPU)`** context instead of the regular `Spawn` as the starting point for the child system.
- Connect from the output (Event) of `Trigger Event On Die` to the `Start` input of `Spawn (GPU)`.
- Connect from the output of `Spawn (GPU)` to the `Spawn` input of the `Initialize` context of the child system.
Step 3: Data inheritance (Inherit) settings
Place `Inherit Source Position` and `Inherit Source Velocity` nodes inside the child system and set the particles to be emitted from the coordinates inherited from the parent. This allows child particles to naturally scatter from the location even if the parent dies while moving.
Practical Checklist & Troubleshooting
| Check target | Confirmation items | Countermeasures/recommended settings |
|---|---|---|
| Child system Capacity | Do you want to keep the default value (64 etc.)? | Increase to 2000 or more depending on the number of simultaneous occurrences. |
| Connection context | Is it via Spawn (GPU)? | Place and connect Spawn (GPU) in the middle. |
| Inherit settings | Is it inheriting the parent's position? | Use `Inherit Source Position`. |
The following is sample code to trigger a custom event in VFX Graph from a C# script and check the behavior of child effects.
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}");
}
}
}
By using this debug script, you can test whether the VFX Graph Sub-emitter correctly receives events and spawns while the game is running without waiting for the entire parent system to operate. It is also effective when optimizing the Capacity threshold while checking the profiler.