Particle System Job System support has moved out of Experimental status in 2019.3.0a9. You can use that minimum version of Unity to make use of this feature, or download an Experimental build from the link below.
The API has changed significantly, in order to support the following key features:
- JobHandle support, allowing you to chain jobs together
- 3 types of job
- a single job with access to all particles (IJobParticleSystem / Schedule)
- a for-each job with access to the particle at the given index (IJobParticleSystemParallelFor / Schedule)
- a batched version of the for-each job, similar to IJobParallelFor vs. IJobParallelForBatch (IJobParticleSystemParallelForBatch / ScheduleBatch)
The biggest change is in how you schedule Particle System jobs. It is now vital that it is done in a new MonoBehaviour callback: OnParticleUpdateJobScheduled. This callback occurs after the native built-in particle jobs are scheduled, and scheduling your jobs here ensures that the managed job runs after the built-in update, and can return a JobHandle that reflects this job-chain. You are able to chain multiple jobs from within this callback.
(eg a job to build a spatial structure of the particles such as a KD-Tree, followed by a job to perform some spatially aware logic such as inter-particle collisions.)
Here is a new example of a (not very exciting) script that works with the latest demo:
using Unity.Collections;
using UnityEngine;
using UnityEngine.ParticleSystemJobs;
public class ParticleJob : MonoBehaviour
{
private ParticleSystem ps;
private UpdateParticlesJob job = new UpdateParticlesJob();
void Start ()
{
ps = GetComponent<ParticleSystem>();
job.color = Color.red;
job.size = 0.35f;
}
void OnParticleUpdateJobScheduled()
{
/*var handle =*/ job.Schedule(ps);
}
//[BurstCompile] // Enable if using the Burst package
struct UpdateParticlesJob : IJobParticleSystem
{
public Color color;
public float size;
public void Execute(ParticleSystemJobData particles)
{
var startColors = particles.startColors;
var sizes = particles.sizes.x;
for (int i = 0; i < particles.count; i++)
{
startColors[i] = color;
sizes[i] = size;
}
}
}
}
Performance
Here is some simple profiling to measure the difference this feature can make.
We created 128 systems, each with 1000 particles (128K particles total). Each system uses a managed job to make its particles chase the cursor.
With Set/GetParticles on the main thread:
Total frame time: 23ms
Particle script code time: 14.7ms
With Managed Burst Jobs:
Total frame time: 8ms
Particle script code time: 0.3ms (main thread) + 0.03ms (jobs across 11 worker threads)
Hopefully this gives an idea of the boost this feature can give - applying a simple behaviour to 128K particles in 0.3ms can unlock a lot of interesting use cases.
Download the Editor here: https://beta.unity3d.com/download/558b031e02d4/public_download.html
Leave us your feedback here: Particle System C# Job System support
=====================================================================
The old experimental version of the feature is described below and has been preserved here for posterity:
We have begun investigating how the C# Job System might interact with the Particle System.
The idea is to allow particles to be manipulated in jobs, with no copying of data (i.e. direct access to the particle data on the native side).
Here is an example of a (not very exciting) script that works with the demo:
using Unity.Collections;
using UnityEngine;
using UnityEngine.Experimental.ParticleSystemJobs;
public class ParticleJob : MonoBehaviour
{
void Start ()
{
var job = new UpdateParticlesJob();
job.color = Color.red;
job.size = 0.35f;
GetComponent<ParticleSystem>().SetJob(job);
}
struct UpdateParticlesJob : IParticleSystemJob
{
[ReadOnly]
public Color color;
[ReadOnly]
public float size;
public void ProcessParticleSystem(JobData particles)
{
var startColors = particles.startColors;
var sizes = particles.sizes.x;
for (int i = 0; i < particles.count; i++)
{
startColors[i] = color;
sizes[i] = size;
}
}
}
}