VFX Graph (Visual Effect Graph) is a powerful tool for drawing hundreds of thousands of ultra-dense particles with GPU (Compute Shader). However, due to the nature of its internal memory management, if you create a project for mobile (iOS/Android) using the development method for desktop PCs, the VRAM (video memory) will quickly become exhausted, turning into a deadly weapon that will cause the OS to forcibly close the app due to OOM (Out of Memory). In this article, we will explain the detailed mechanism by which VFX Graph consumes GPU memory, as well as optimization techniques to ensure safe operation on actual mobile devices.
1. VFX Graph's GPU buffer pre-allocation trap
The biggest difference from Shuriken (traditional CPU-based Particle System) is that VFX Graph stores and controls all particle data in structured buffers (StructuredBuffer / GraphicsBuffer) on the GPU. This buffer pre-allocates memory equal to the Capacity setting in the VFX the moment an instance of the effect is activated, regardless ofhow many particles the effect is currently displaying.
The physical data size of the buffer allocated on VRAM is strictly defined by the following formula.
What is important here is the "total attribute data size." VFX Graph maintains various "Attributes" for each particle. For example, position (`position`: Vector3 = 12 bytes), velocity (`velocity`: Vector3 = 12 bytes), color (`color`: Vector4 = 16 bytes), size (`size`: Float = 4 bytes), and lifetime and elapsed time (`lifetime`, `age`: Float × 2 = 8 bytes). Adding these up, even simple particles require about 50-100 bytes of memory per particle.
If you set the `Capacity` of an effect to `100,000` (100,000) without thinking deeply, then with just one instance:
100,000 × 80 bytes × 2 = approximately 16,000,000 bytes (approximately 16MB)
's VRAM is consumed whenever the game object exists in the scene. If you instantiate this in 10 places in-game, such as enemy death effects, weapon hit effects, etc., that alone will result in **160MB** of VRAM being lost even when idle. Mobile devices use a "Unified Memory" architecture where the CPU and GPU share memory, so excessive consumption of VRAM directly leads to exhaustion of the entire system memory and immediately causes an OOM crash.
2. Thoroughly eliminate wasteful attributes.
A powerful approach to reducing memory consumption, along with reducing `Capacity`, is **``reducing the attribute byte size per particle''**. VFX Graph automatically detects attributes that have been called at least once in the graph via a `Set Attribute` or `Get Attribute` node, or used in an implicit computation (such as Physics or Collision) and includes them in a buffer structure.
Many developers leave experimental nodes on the graph, or store data that can be substituted with different values as separate attributes. For example, when changing the color of a particle over time, instead of continuing to store the `color` attribute (16 bytes) in the buffer, if you design it to dynamically calculate (sample) it at the Vertex/Fragment stage in the shader using the `age/lifetime` ratio (0 to 1) from the gradient texture, the `color` attribute itself can be completely removed from the buffer, saving 16 bytes per particle.
3. Three rules for optimizing VFX Graph for mobile
When using VFX Graph in practice, please implement the following optimization settings and checklist into your pipeline.
① Strict mathematical formula design for Capacity
Stop manually entering the value of `Capacity` in the inspector as an arbitrary round number (e.g. 1000 or 10000). `Capacity` calculates the upper limit value using the following formula from `Rate` (the number of particles generated per second), which is the frequency of particle generation, and `Lifetime`, which is the maximum lifespan of particles.
For example, for an effect that generates 50 particles per second and has a maximum lifetime of 3 seconds, the required capacity is `50 × 3 × 1.2 = 180` particles. Instead of leaving it at the default value of `1,000`, enter exactly `180` under `Capacity` in the Inspector. This alone can reduce memory consumption by approximately 82%.
② Audit the VFX Graph's "Attributes List"
From the settings window at the top left of the VFX Graph editor (or VFX asset inspector), check the list of "Attributes" that the graph requests from the GPU buffer. If unused attributes (e.g. `targetPosition`, `size3D`, `axisX`, etc.) are included in the buffer allocation target, completely delete the unused nodes (grayed out dead nodes, etc.) that set or retrieve them in the graph. Make sure that the number of bytes in the buffer is smaller after compilation.
③ Introduction of Dynamic Spawn Control
In scenes where the number of VFX generated temporarily increases due to a large number of objects dying at the same time, etc., the spawn rate of VFX is dynamically controlled from a C# script to limit the total number of particles on the entire screen (managed all at once using VFX Manager, etc.). Also, once the effect has finished playing (or is no longer visible off-screen), the game object should be immediately `SetActive(false)` or `Destroy`, and the pre-located area of the GPU buffer will be immediately released (returned to the Metal/Vulkan memory pool) to ensure lifecycle management.