Updating particle angularVelocity at runtime

I have a what I thought was going to be trivially simple situation where I want (shuriken) particles to bounce away (in a particular manner) and start spinning in response to hitting a collider.
I tackled the bounce part first.

  1. set up Particle System
  2. enable Trigger module
  3. attach script, catch OnParticleTrigger
  4. GetTriggerParticles, iterate, assign new .velocity, SetTriggerParticles
    This much works just fine- particles hit the collider, and on enter, they get plinked away exactly where I tell them to go. So the fundamentals of the read-write-update flow are sound.

Now, I wanted to add rotation for a bit more visual energy.
I tried updating .angularVelocity right after I update .velocity. A Debug.log shows the new value, but the particles don’t spin.
I tried turning on the Rotation over Lifetime module in case that somehow enabled dynamic update calculations. Particles spin globally, and I can see the RoL values showing up in debug logging, and I can see my new values after I assign them, but the particles still only visually rotate in accordance with the RoL-initialized value.
I tried both of the above with the z-axis of split-axis .angularVelocity3D with essentially identical result.

Is it simply not possible to change a particle’s spin speed after emission in Unity (2019.4.14f1) without building a full custom VFX Graph solution, or am I missing a flag somewhere to tell shuriken to actually write back angularVelocity changes and use them in system updates?

Yep, there’s some sort of bug. I just tried to get it to work with a vanilla particle system and nothing happens, so I started playing around with the modules. Nothing was still working until I first enabled Rotation Over Lifetime, disabled it, and then everything started working as you’d expect. You might want to file a proper bug report.

Here’s a working code based solution / workaround:

public sealed class ChangeAngularVelocity : MonoBehaviour
{
   private void Start()
   {
       StartCoroutine(Tick());
   }

   private IEnumerator Tick()
   {
       ParticleSystem particleSystem = GetComponent<ParticleSystem>();
       ParticleSystem.Particle[] particles = new ParticleSystem.Particle[particleSystem.main.maxParticles];

       // UNCOMMENT THIS SECTION AND EVERYTHING WILL WORK:
       /*
       ParticleSystem.RotationOverLifetimeModule rotationOverLifetime = particleSystem.rotationOverLifetime;
       rotationOverLifetime.enabled = true;

       yield return null; // you have to wait a frame or it won't work

       rotationOverLifetime.enabled = false;
       */

       while (enabled == true)
       {
           int count = particleSystem.GetParticles(particles);

           for (int i = 0; i < count; ++i)
           {
               particles[i].angularVelocity = Random.Range(0f, 360f);
           }

           particleSystem.SetParticles(particles, count);

           Debug.LogFormat("Changed {0} particles", count);

           yield return new WaitForSeconds(0.2f);

       }
   }
}

You absolutely have to wait a frame before disabling it or it won’t work.

Particle system with enabling/disabling commented out:

Particle system with enabling, yielding a frame, disabling:

Yep please give us a bug report :slight_smile:

Thanks! I may need to just inline GroZZler’s sample into the report. Notwithstanding NDA, by the time I find these things it’s usually in a project with a million other dependencies that takes upwards of 5 mins just to open, and reducing it to an isolated repro case can be hell.

tracked! Unity Issue Tracker - particles.angularVelocity function doesn&#39;t change particle&#39;s angular velocity when changed via the script

1 Like

Bug received! Thanks!

thanks a lot