Cover image

Using Particle Systems with ECS in Unity

This tutorial assumes you are already familiar with Unity itself and the ECS API!

I’ve been upgrading more systems to Unity’s ECS (Entity Component System) for my game. One of the things are these “drones” that shoot projectiles at the player. So I had to figure out how to use particle systems with entities and figured I’d explain how I did it.

Setting up

Lets start by creating a tag component. Tag components are called like that because they contain no data, they are used to “tag” entities by acting like markers. We will add this component to entities we want to emit particles from.
You can learn more about IComponentData in the ECS docs.

using Unity.Entities;

public struct VfxEmitter : IComponentData { }

Then create a new file and set up a basic ECS system. This will be the script in charge of spawning the particles.

using UnityEngine;
using Unity.Entities;
using Unity.Transforms;

public class VfxSystem : SystemBase
{
  protected override void OnCreate()
  {
    base.OnCreate();
    Enabled = false; // Dont run the system until we have given it a ParticleSystem to use
  }

  protected override void OnUpdate()
  {
    // Empty for now
  }
}

The particles in the scene

Now we can create the actual particle effect. This is done as usual, with a built-in ParticleSystem.
For example here is what I made:

Remember to turn off Looping, PlayOnAwake and Emission since we will be controlling emission from our script (You can have them enabled while you create your effect, but make sure at least PlayOnAwake is off when actually running the game. Otherwise the particles will start spawning immediately and not at the entities’ positions).

screenshot of inspector of particle system with correct settings

Now we need to get a reference to the particle emitter in the scene from the ECS system. This can be done in many different ways, for example using Find or by instantiating it at runtime.
For the purposes of this tutorial we’ll just make a quick and dirty helper scripts that finds the system and passes it our ParticleSystem from the game scene.

using Unity.Entities;
using UnityEngine;

public class VfxSystemHelper : MonoBehaviour
{
    public ParticleSystem particles;

    void Start()
    {
        World.DefaultGameObjectInjectionWorld.GetOrCreateSystem<VfxSystem>().Init(particles);
    }
}

Then we create the function that gets called by the helper script. This function receives the reference and then enables the system to make it start running.

public class VfxSystem : SystemBase
{
    UnityEngine.ParticleSystem particleSystem;
  
    protected override void OnCreate() // ...
    
    public void Init(UnityEngine.ParticleSystem particleSystem)
    {
        this.particleSystem = particleSystem;
        Enabled = true; // Now we have a ParticleSystem, can begin running the system
    }

    protected override void OnUpdate()

Emitting custom particles

And now lets make it actually emit particles! We’ll do this by using the EmitParams API.

Note that the entity must have a Translation component (from Unity.Transforms), in addidion to the VfxEmitter component we created at the start of this tutorial.

For each entity that has our tag component attached the system will setup an EmitParams struct with the entity’s position and tell the ParticleSystem to emit a particle using it.

UnityEngine.ParticleSystem particleSystem;
UnityEngine.ParticleSystem.EmitParams emitParams;
protected override void OnUpdate()
{
   Entities.WithAll<VfxEmitter>().ForEach((in Translation translation) =>
   {
       emitParams.position = translation.Value;
       particleSystem.Emit(emitParams, 1);
   }).WithoutBurst().Run();
}

Frame-rate indipendence

There is a problem however, the number of particles spawned depends on the framerate!
We are emitting one particle for every time the Update function is executed. So if the game is running at 30fps that will be 30 particles; but if the game runs at 60 it would spawn 60. And it’s even worse if the framerate is not constant!
We can fix this by setting a fixed emission rate, similar to how the builtin emission would work. First, set up some variables.

UnityEngine.ParticleSystem particleSystem;
UnityEngine.ParticleSystem.EmitParams emitParams;
const float particlesPerSecond = 2f;
const float interval = 1f / particlesPerSecond;
double nextSpawnTime;

Set particlesPerSecond toa value appropriate for your effect.

And update the code so that the emission only happens after the time defined by interval has elapsed.

protected override void OnUpdate()
{
   var time = Time.ElapsedTime;
   if (time >= nextSpawnTime)
   {
       nextSpawnTime = time + interval;
        Entities.WithAll<VfxEmitter>().ForEach // [...]
        // [...]
        }.Run();
   }
}

Particles with ECS!

And this is the result in game:

Look at them go!

Doing more & Limitations

You can add a field to the tag component to store things like scale or color for that entity. Rememeber to use a shader compatible with ParticleSystems.
Another limitation is that for more complex emission patterns you must create the logic yourself!
There is a way to fix this a bit and which also makes it possible to make utse of the “shape” module of the ParticleSystem. This is done by moving the entire particles transform and emitting using particleSystem.Play() at each entity’s position. Works better for burst or explosions for example.
(I might write a tutorial on these things too if there’s enough request!)

Download files

The Standard package contains the script to put on the entity and the system. The Premium package, instead, also contains a test scene which includes the helper script.

Preview of the example scene

Enjoying the tutorials? Are they useful? Want more?

If you think these posts have either helped or inspired you, please consider supporting this blog.

Help this blog continue existing

If the knowledge you have gained had a significant impact on your project, a mention in the credits would be very appreciated.

Silo27 Logo
Enrico Monese

All around developer, from games and web to weird commandline utilities. 2D/3D art, with a good care for UI/UX and clean design.

Twitter Twitter Patreon Patreon Blog Blog   Reddit Reddit Github Github Gitlab Gitlab ArtStation ArtStation Mail Mail