Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

(Case 945823) Changing ParticleSystem emission causes unstable frame-rate

Discussion in '2017.2 Beta' started by Peter77, Aug 27, 2017.

  1. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
    Changing the emission.rateOverTimeMultiplier property of a ParticleSystem during runtime, causes the frame-rate to get very unstable in my game and the extracted test-project that I attached to the bug-report.

    In my tests, the time spent for changing the rateOverTimeMultiplier property is between 0.5ms to 10ms. By average, changing rateOverTimeMultiplier costs about 1ms in my tests, which is a lot already imo, considering the low emission amount (max 50 per sec). Please note that these numbers vary depending on hardware.

    Please see the video and screenshot that I attached to the bug-report.


    Why changing rateOverTimeMultiplier at runtime?
    If the player character enters the radius of a light, a ParticleSystem is used to emit dust particles around the players position.

    The amount of particles that are emitted depends on the distance between the player and the light. The closer the player gets to the light, the more particles are being emitted. The ParticleSystem is part of the player GameObject hierarchy.

    This approach is much less memory demanding, if the scene contains a lot of light sources, than adding a ParticleSystem to every Light in the scene.

    Code (CSharp):
    1. void TestCode.Update()
    2. {
    3.    var em = LightParticles.emission;
    4.  
    5.    // LightSensor.Weight is between 0..1,
    6.    // therefore rateOverTimeMultiplier changes between
    7.    // emitting 0..50 particles per second.
    8.    em.rateOverTimeMultiplier = 50 * LightSensor.Weight;
    9. }
    profiler_a_2017_2.png

    profiler_b_2017_2.png


    Reproduce
    • Open user attached project
    • Press File/Build & Run to build a Windows Standalone 64bit player
    • Start Player
    • Connect Profiler to running Player
    • Select in Profiler Update.ScriptRunBehaviourUpdate/BehaviourUpdate/TestCode.Update()
    Observe that the time Unity spends in TestCode.Update(), which sets the rateOverTimeMultiplier property, varies a lot and causes enormous performance spikes.


    Expected
    Changing rateOverTimeMultiplier during runtime should not cause performance to drop. I assumed changing rateOverTimeMultiplier would cost almost 0ms, especially at this low emission rates (0..50).
     
  2. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,285
    I can't check this properly until later in the week, but I just wanted to verify with you that LightSensor.Weight is not to blame?

    Assuming that is just a simple property accessor, my next guess is that modifying particle systems in LateUpdate can cause scripts to stall while the particle update job finishes. The Timeline Profiler would give more insight into this. (If you're even doing this in LateUpdate)

    Or, of the course, the other possibility is that it's a bug :) but just some speculation for now until I can check it out properly.
     
  3. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
    Hi Richard, thank for your reply. That's great!

    I replaced the code with this, to rule out LightSensor.Weight being the issue:
    Code (CSharp):
    1. void TestCode.Update()
    2. {
    3.     var em = LightParticles.emission;
    4.     em.rateOverTimeMultiplier = 50 * Mathf.Abs(Mathf.Sin(Time.time * 0.2f));
    5. }
    Unfortunately, I can still see the performance spikes as reported in my initial post.

    The code runs in Update, but I moved it to LateUpdate and the stall seems to be gone. At least in the test-project. I've to check this in the real project later. I'm not certain, is this a good sign?

    I've attached a screenshot of the Timeline Profiler. This has been taken with the updated code that uses Mathf.Sin rather than LightSensor.Weight.
    profiler_timeline.png

    I've also uploaded a Profiler recording of my recent test. You can download it from:
    http://www.console-dev.de/tmp/case_945823_timeline_profiler.zip
     
  4. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
    Did you have a chance to take a look at it already?
     
  5. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    2,285
    Hey, I checked it in our latest version (2017.3) but couldn't reproduce the problem. It's still on my todo list to have a go in 2017.2 sorry!
     
    Peter77 likes this.
  6. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
    I was testing if it helps if I move the code that writes to emission.rateOverTimeMultiplier to LateUpdate and FixedUpdate. Unfortunately it didn't make a difference, the up to 10ms stall keeps occurring. I'm out of ideas.

    BTW, the stall occurs only in a build, it does not reproduce in the editor.

    I imagine one reason you couldn't reproduce the issue might be because your development machine is rather high-end tech. Perhaps you can give it a try on a setup similar to the specs of the machine that I used to submit the bug-report.
     
    Last edited: Sep 17, 2017
    richardkettlewell likes this.
  7. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,618
    Writing to emission.rateOverTimeMultiplier stalls up to 10ms even if the GameObject of the ParticleSystem is disabled.
    Code (CSharp):
    1. void UpdateLightParticles()
    2. {
    3.     var em = LightParticles.emission;
    4.     em.rateOverTimeMultiplier = 50 * Mathf.Abs(Mathf.Sin(Time.time));
    5. }
     
    Last edited: Sep 17, 2017