Particle System Trail Ribbon Mode indexing seems wrong when >= 32 particles & setting positions

Been trying to find info on this issue but it’s tough due to the words being so general…

I’m noticing that when using a Particle System Trail module, when the particle count goes over 31, the indexing order “along the trail” starts getting out of order.

For example, I have a simple IParticleSystem that sets positions of particles to create a line, my expectation is that in Ribbon Mode (with max 1 ribbon), if I have 8 particles, it should be a chain like this:

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7

I ensure that my Particle System has no emission, does not auto-play. And then in the code that schedules the IParticleSystemParallelFor job, it simply does this once on initialization:

main.maxParticles = nodeCount;
fx.Clear(true);
fx.Emit(nodeCount);

then the job runs and does this to modify the particle positions:

public void Execute(ParticleSystemJobData jobData, int index)
{
    var node = nodes[index];
    var positions = jobData.positions;
    positions[index] = node.positionWS;
    var velocities = jobData.velocities;
    velocities[index] = node.positionWS - node.prevPositionWS;
    var times = jobData.aliveTimePercent;
    times[index] = 0.5f;
}

my job code assumes that it is dealing with a long strip (like the 0 to 7 sequence example above), all works fine when my nodeCount (or particle count) is at 31 or below, but when I start to go over 31, I get “stray” particle ribbon strips connecting back, like it is indexing into the particle system incorrectly.

The thing is, I have my own Debug.DrawLines to show my where my segments are using the positions from the job, and they are always correct (never exhibiting the indexing issue the particle system has). So I’m pretty sure that the problem lies within the Particle System.

I’ve also tried each IParticleSystem job type but didn’t find any differences in behaviour. EDIT Also worth noting, I get the same issue when using GetParticles / SetParticles.

Any ideas? sorry to tag you @richardkettlewell I could probably make a repro project of this but need some time to isolate it…

Attached are screenshots showing how the Particle System indexing is out of order. I couldn’t find any number greater than 31 where the indexing is correct…

EDIT On further inspection… it looks like it is always affected in sections of 32, so at 64 particles, it looks like particle 31 is treated as connecting to particle 63, and particle 32 seems to connect to particle 0. Then at 128 particles, I get similar splits but doubled again… and so on…

Is it some issue with internally how Unity dispatches work for the particle systems?

I’ve created a simple test project and submitted a bug report. I believe this unusual indexing could be reverse engineered and turned into a helper function to remap the index. So if it turns out Unity can’t fix this due to it being a “bug that is now a feature” then having a function in documentation to translate to the indexing that the particle system trail uses would be very beneficial.

attached is a simple test script and gif of the problem

9614705–1364498–ParticleSystemTest.cs (2.2 KB)
9614705--1364501--Unity_Z38UxMgHij.gif

was trying to see if a specific pattern was followed (with the order that the particle trail moves through the indices set by SetParticles)

the order is as follows for some examples:

count <= 31
0-30

count == 32
31,0-30

count == 33
15,0-14,16,32,17-31

count == 34
33,0-32

count == 35
16,0-15,17,34,18-33

count == 36
35,0-34

count == 37
17,0-16,18,36,19-35

count == 38
37,0-36

count == 62
61,0-60

count == 63
30,0-29,31,62,32-61

count == 64
62-31,0-30,63

count == 65
33-64,32,0-31

count == 66
34-64,33,32,0-14,65,15,17-31,16

count == 67
34-48,66,49,51-65,50,33,0-14,32,15,17-31,16

count == 68
35-49,34,50,52-66,51,33,0-32,67

count == 69
35-68,34,0-33

count == 70
36-68,35,34,0-15,69,16,18-33,17

count == 129
65-96,127-97,128,64,0-31,62-32,63

We connect the ribbon points based on how long the particles have been alive. so we connect from newest → oldest.
Particles with identical alive times may not connect in the order you expect, so I guess this code is causing the problem:

times[index] = 0.5f;

I’m not sure ho important the alive time is to you, but, perhaps try to replace it with something like:

times[index] = epsilon * (float)index;