Quick answer: Event name is case-sensitive — must exactly match the Event context in the graph. The effect must be playing (Play() was called or auto-play is on). Use SendEvent from script; GPU events only link systems within a single VFX Graph.

Here is how to fix Unity Visual Effect Graph event not firing. You define a custom event “Impact” in your VFX Graph. On hit, you call vfx.SendEvent("Impact"). Nothing happens. You switch to another Event name that works (OnPlay) and confirm the graph reacts — so the graph is alive. The custom event is simply silent.

The Symptom

VFX Graph custom events do not fire when SendEvent is called. The graph is loaded, plays on OnPlay, responds to exposed parameter changes — just not to custom events. No errors in the console.

What Causes This

Event name typo. Strings. Case-sensitive. SendEvent("impact") does not match an Event context named “Impact.”

Event context missing. The VFX Graph must have an Event context with the matching name. Without one, the SendEvent call has nowhere to connect. Check your graph’s top-level contexts.

Effect stopped. If the effect is in Stopped state, SendEvent does nothing. The effect must be playing. visualEffect.Play() first, then SendEvent works.

GPU events are graph-internal. Trigger Event blocks inside particle update steps fire GPU events that feed other systems within the same graph. They cannot trigger events on a different VFX instance.

Binding attribute not passed. For events with attributes (position, velocity), use SendEvent with VFXEventAttribute. Bare SendEvent("Name") fires the event but attributes stay at defaults.

The Fix

Step 1: Verify event name. Open the VFX Graph. Check top-level Event contexts. Note exact names. In script, use const strings to avoid typos:

using UnityEngine;
using UnityEngine.VFX;

public class HitEffect : MonoBehaviour
{
    [SerializeField] private VisualEffect vfx;
    private const string IMPACT_EVENT = "Impact";

    public void OnHit()
    {
        if (!vfx.HasEvent(IMPACT_EVENT))
        {
            Debug.LogError($"VFX missing {IMPACT_EVENT} event");
            return;
        }
        vfx.SendEvent(IMPACT_EVENT);
    }
}

HasEvent returns true if the graph has a context with that name. Use as a guard to catch typos at runtime.

Step 2: Ensure the effect is playing. If the effect is Stopped, Play() before SendEvent:

public void TriggerImpact(Vector3 position)
{
    vfx.transform.position = position;
    if (!vfx.aliveParticleCount > 0)
        vfx.Play();

    vfx.SendEvent(IMPACT_EVENT);
}

For impact effects that should trigger repeatedly without calling Play each time, set the graph’s Initial Event Name in the Visual Effect inspector to your custom event, or configure the graph to stay alive indefinitely with an OnPlay/OnStop pair.

Step 3: Pass attributes with VFXEventAttribute. For events that need data (spawn position, velocity vector):

public void TriggerAt(Vector3 pos, Vector3 vel)
{
    VFXEventAttribute attr = vfx.CreateVFXEventAttribute();
    attr.SetVector3("position", pos);
    attr.SetVector3("velocity", vel);
    vfx.SendEvent(IMPACT_EVENT, attr);
}

In the graph, add attribute Get nodes in the spawn context to read the passed values. Without passing attributes, particles spawn with default positions (origin) and zero velocity.

Step 4: Use GPU Trigger Events for graph-internal chains. If you want one system inside the graph to spawn particles in another system (e.g. trail emits sparks), use Trigger Event Always, Trigger Event Rate, or Trigger Event On Die blocks in the update context. These fire GPU events consumed by the linked system’s Event context.

GPU events cannot be triggered from script. They are entirely within-graph.

Debugging Events

Enable the VFX Graph debug overlay:

fx.Visual.Effects.Profiler 1  // console command

Shows event fire counts per frame. If your SendEvent call does not increment the Impact event counter, the call is not reaching the graph (wrong effect, wrong name, effect stopped).

“VFX Graph events are strings into a list of contexts. Get the string right, confirm the context exists, and fire only when the effect is alive.”

Related Issues

For Niagara issues in Unreal, see Unreal Niagara Not Spawning in Packaged Build. For Unity particle system issues, Particle Stop Not Stopping Immediately.

HasEvent check. Play before SendEvent. Attribute passing for data. Three habits.