Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How do I alter live Particles

Discussion in 'Scripting' started by knobblez, Aug 7, 2022.

  1. knobblez

    knobblez

    Joined:
    Nov 26, 2017
    Posts:
    223
    Hello, I wanted to adjust the remainingLifetime of live particles(individual particles, not the whole particle system). I wanted to set their remainingLifetime to less than zero(destroy them) if they fall below a value on the y axis. The reason I don't want to use collisions is because the y value I'm checking against is always changing.

    Here is the code I've got:


    Code (CSharp):
    1.         private void LateUpdate()
    2.         {
    3.             if (liveParticles == null || liveParticles.Length < ps.main.maxParticles)
    4.             {
    5.                 liveParticles = new ParticleSystem.Particle[ps.main.maxParticles];
    6.             }
    7.  
    8.             if (liveParticles != null)
    9.             {
    10.                 numParticlesAlive = ps.GetParticles(liveParticles);
    11.             }
    12.  
    13.             for (int i = 0; i < numParticlesAlive; i++)
    14.             {
    15.                 if (Water != null)
    16.                 {
    17.                     waterHeight = Water.GetHeightAtPoint(liveParticles[i].position);
    18.                 }
    19.                 else
    20.                 {
    21.                     return;
    22.                 }
    23.  
    24.                 if (liveParticles[i].position.y <= waterHeight)
    25.                 {
    26.                     liveParticles[i].remainingLifetime = -1f;
    27.                     ps.SetParticles(liveParticles, 1, i);//added this but it changes all of them
    28.                 }
    29.             }
    30.         }
     
    Last edited: Aug 7, 2022
  2. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,528
    Well, the particles live inside the particles system on the native side. When you use "GetParticles" you essentially copy the information of each particle inside the specified range into your array. You can modify the data of the particles in your local array and once you're done you can write the data back. You're mixing two completely different usecases here. Both GetParticles and SetParticles allow to just grab / set a subset of particles by specifying an offset and a size. This offset is simply an offset into the internal array of particles. So assume there are 10 particles in the system

    [A, B, C, D, E, F, G, H, I, J]


    When you use
    num = GetParticles(yourArray, 3, 4);
    your array would be filled like this
    [E, F, G, X, X, X, X, X, ...]

    So you grab the first element at offset 4 and only 3 elements which are copied to the start of your array. I've marked the unused elements of the array with X as those are not changed. "num" would be 3, since the method copied 3 elements into your array.

    When you want to write them back to the system, you essentially use the same parameters, though use "num" instead of 3 since you could have been reading too many elements and they cut off:
    SetParticles(yourArray, num, 4);


    Since you copy the whole array, you have to write the whole array. Using a different offset here makes no sense as it is the target offset, not the offset into your array. So you currently copy just the same first element in your local array onto every slot in the native array.

    You should just call
    SetParticles(liveParticles);
    after your for loop to update the particles. That's all. This is a block copy operation since "Particle" is a struct.
     
    knobblez likes this.
  3. knobblez

    knobblez

    Joined:
    Nov 26, 2017
    Posts:
    223
    You are awesome! Thank you. It also helped to change simulation space to World...haha.