1 like 0 dislike

Hello! I'm trying to get a particle's ID#. It seems using EmittedCount on an evolver script is the best way to do it since it will give you the number of particles at the start of each frame. Trying to swap the Up Axis on every other particle:

     AxisUp = select(float3(0,0,1), float3(0,1,0), EmittedCount % 2);

The documentation states:

Layer spawn-scripts not yet available. In 1.8 you can only use layer evolve scripts.

but I'm getting this error when adding that line to my evolver script:

L_3: Unresolved Symbol: "EmittedCount"

Is there a better way to get a particle's ID? Am I missing something? Or am I doing this completely wrong?



by gtapperdesign (1k points)
On a related note...

I'm creating a chain link effect, but I need to adjust the SpawnCount  based on the distance of the target otherwise the links will overlap when the target is too close and there will be gaps in the chain when the target is too far.

SpawnCount is readable only. Is there a workaround for changing this? Inside of Unity or Popcorn. Can you expose the SpawnCount??
You can either write to 'Flux' inside the layer script, or create an attribute that you control inside Unity and bind that to the 'FluxFactorExpression' property of your layer.
More details here: http://wiki.popcornfx.com/index.php/Particle_tips_FluxFactorExpression

1 Answer

2 like 0 dislike
Best answer

Hi Gregory,

The Scripting documentation might not be very clear about this, but you seem to try using this in a layer script. Is that correct?

TL;DR / Quick way to fix:

Put your 'AxisUp' line in the particle spawn script and change it to:

     AxisUp = select(float3(0,0,1), float3(0,1,0), spawner.EmittedCount % 2 != 0);

And it should work.


Details on why it doesn't work this way :

The layer evolve script is run once per frame for each layer. your layer might very well spawn 100 particles that frame, your script will only be run once.
You can't touch any particle fields in the layer script, because there would be multiple particles for a single execution of the script, and these particles haven't been born yet when the layer script is run.

So even if you could write to 'AxisUp', as it only gets run once for all the particles run this frame, all those particles would get the same 'AxisUp'.

The layer script allows you to touch some properties of the emitter itself, like the 'Flux' (that will allow you to control the emission rate this frame), or the Positions/Orientations.

For what you're trying to achieve, you need to do this in the particle spawn script.

In there, you can use "spawner.EmittedCount". The spawn script will be run for each particles, and you'll see 'EmittedCount' changing properly, and your select will work as expected.

There's another problem in that line of script though:

     AxisUp = select(float3(0,0,1), float3(0,1,0), spawner.EmittedCount % 2);

The third argument of 'select' is the result of a conditional test. which is a 32-bits int selection mask. which is either 'false' (0) or 'true' (0xFFFFFFFF --> all bits set to '1' in the 32-bits integer, which also happens to be the value -1)

spawner.EmittedCount % 2 will return an int which will be either 0 or 1. And it will not work with the select.
Here, select will always return the first value.

The proper way to do this is:

     AxisUp = select(float3(0,0,1), float3(0,1,0), spawner.EmittedCount % 2 != 0);

Notice the '!= 0' at the end. This correctly returns either 'true' or 'false', and the select will now work.
As 'true' is also '-1', you could also hack things around like this:

     AxisUp = select(float3(0,0,1), float3(0,1,0), -(spawner.EmittedCount % 2));

When the modulo returns, select will receive 0 and return the first value, when the modulo returns 1, select will receive -1 and correctly select the second value.
But I'd advise against using such tricks. I mention this just to make things clearer, but it'll make your scripts more arcane and difficult to pick up if you or someone else needs to get back to them after a couple months or so :)


Spawn count question :

About your second question regarding the SpawnCount, you can't change SpawnCount directly, but you can change 'Flux' Inside the layer script. Flux is a multiplier on top of the regular spawn count, FluxFactorExpression, and Flux curve. If you want to set the exact spawn count, you can just set the spawn count to 1 in your layer, and set 'Flux' to whatever real value you need.



by jbilalte (33.5k points)
Also, if you wonder what calling 'select' with other integer values actually does, it just does a simple bitwise selection. So in your case, it only selected the least significant mantissa bit of the IEEE754 floating-point values, but always kept the other bits coming from the first value. as the values you were selecting were zeroes or ones, which both have that least significant bit to zero anyway, you always got the exact same number.

In theory you could use that to do stuff like, transfer the sign of a float, with something like:

MyValue = select(a, b, 0x80000000);

this will return 'a' but with the sign of 'b'. if a is positive but b is negative it will return -a, etc..

but you really should avoid doing stuff like that, even if it will work in the editor on PC/windows, there is NO GUARANTEE it will work on other platforms.
you can hack around the select, but giving it values other than 'true' or 'false' is undefined behavior, meaning you won't be sure it'll work the same way on all platforms. it might work as expected on one, but break on the others.
for example, the sign copy trick above will, on some platforms, copy the entire value of 'b', not just the sign.

anyway... :)
Sweeeet! This all worked! The flux functions are super useful too.

Mind = blown on the select() lol I'm assuming the same goes for iif(), just swapped aesthetically
that's correct :)
iif uses select under the hood, it's just syntactic sugar.