# 6. VFX Graph Performance and Quest Part of [[VFX Graph]]. Previous: [[5. VFX GraphicsBuffers and Audio-Reactive Effects]]. Next: [[7. VFX Graph Pitfalls]]. > [!note] Verification status > From the 17.5 Requirements page: compute + SSBO required, **no OpenGL ES**, URP support **not out of preview** (only some URP platforms). The older "What's new in 12" page says URP high-end mobile support covers "a subset of high-end mobile devices" and recommends the built-in Particle System "for most mobile applications". `VisualEffect.culled`, `playRate`, `allowInstancing` exist on 6000.5. **Not verified:** an official statement that Quest 2 is a supported VFX Graph target - a Unity staff forum post (2023) says they tested on Quest 2 without reproducing a specific bug, which is anecdotal, not a support statement. **VR version note:** Quest work in this vault targets **Unity 6.3 LTS (6000.3.27f2+)** ([[0.Choosing a Unity Version]]), whose VFX Graph is the 17.3 line. Re-check the 17.3 requirements page before shipping. ## 6.1 Where VFX Graph spends time | Cost | Where | Fix | |---|---|---| | Simulation | Compute, scales with **alive** particles and Update blocks | Fewer blocks, shorter lifetimes, cheaper turbulence | | Memory | GPU buffers sized by **capacity** | Capacity = real peak, not "just in case" | | Culling failures | Wrong **bounds** -> simulates/renders off-screen or pops | Recorded or Manual bounds | | Overdraw | Fragment cost of transparent quads | Smaller particles, fewer layers, opaque/alpha-clip where possible | | Sorting | Transparent sort per frame | Disable sorting for additive effects (order doesn't matter) | | Per-instance overhead | Many VisualEffect components | One instance + events (part 3); **instancing** for identical graphs | ## 6.2 Script: distance LOD for effects Scale spawn rate with distance and stop updating effects nobody can see. ```csharp // Assets/Scripts/VFX/VfxDistanceLod.cs using UnityEngine; using UnityEngine.VFX; [RequireComponent(typeof(VisualEffect))] public class VfxDistanceLod : MonoBehaviour { public Transform viewer; // camera; defaults to Camera.main public float fullDetailDistance = 15f; public float cutoffDistance = 60f; [Tooltip("Exposed float multiplying spawn rate in the graph")] public string rateProperty = "RateScale"; public float checkInterval = 0.25f; VisualEffect vfx; int rateId; float timer; void Awake() { vfx = GetComponent<VisualEffect>(); rateId = Shader.PropertyToID(rateProperty); if (viewer == null && Camera.main != null) viewer = Camera.main.transform; } void Update() { timer -= Time.deltaTime; if (timer > 0f || viewer == null) return; timer = checkInterval; float d = Vector3.Distance(viewer.position, transform.position); float scale = 1f - Mathf.InverseLerp(fullDetailDistance, cutoffDistance, d); if (vfx.HasFloat(rateId)) vfx.SetFloat(rateId, scale); // Beyond the cutoff, stop simulating entirely; resume when back in range. vfx.pause = scale <= 0f; } } ``` In the graph, multiply **Constant Rate** by `RateScale`. Pausing far effects saves compute; the effect resumes where it left off. ## 6.3 Quest 2 guidance - **Graphics API:** Vulkan only. VFX Graph doesn't support OpenGL ES; remove GLES from the Android Graphics APIs list or the capability gate (part 1) will fall back. - **Budget:** start with **one or two** VFX Graph systems on screen, low thousands of particles total. Quest 2's mobile GPU shares its budget with stereo rendering at 72-90 Hz ([[5.Quest 2 Performance and Rendering]]). - **Overdraw is still the killer** - everything in [[5.VFX Graph Comparison and Performance]] about Shuriken overdraw applies equally to VFX Graph quads. - **Avoid** depth-buffer collision, scene-color distortion, soft particles and volumetric outputs in VR unless profiled - each needs extra screen-size passes or textures. - **Lit outputs** are expensive; use unlit additive/alpha outputs with emissive color. - **Prefer the Particle System** for hit sparks and small bursts on Quest. Reserve VFX Graph for the one effect that needs huge counts (a swarm, a storm), and keep a Shuriken fallback via `VfxCapabilityGate.forceFallback` on the Quest quality level. - **Test on device early.** Editor GPU != Adreno 650. ## 6.4 Profiling 1. **Visual Effect** inspector: debug info (alive count, bounds) and the graph's **profiling/debug** panels where available. 2. **Frame Debugger:** count VFX draws; confirm instancing batches identical graphs. 3. **GPU profiler / RenderDoc / OVR Metrics Tool on Quest:** compute dispatch time and fragment time. ## Sources - Requirements and compatibility (17.5): https://docs.unity3d.com/Packages/[email protected]/manual/System-Requirements.html - What's new in version 12 (mobile compute guidance): https://docs.unity3d.com/Packages/[email protected]/manual/whats-new-12.html - Instancing: https://docs.unity3d.com/Packages/[email protected]/manual/Instancing.html - `VisualEffect` (culled, pause, playRate, allowInstancing): https://docs.unity3d.com/6000.5/Documentation/ScriptReference/VFX.VisualEffect.html - Forum thread on VFX Graph mobile compatibility (staff answers, anecdotal Quest 2 test): https://discussions.unity.com/t/vfx-stop-working-when-update-2021-3-16f1-to-2022-or-2023/904038