Search Unity

  1. Unity 2018.3 is now released.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. We've updated our Terms of Service. Please read our blog post from Unity CTO and Co-Founder Joachim Ante here
    Dismiss Notice
  4. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  5. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

[Feedback] Ringbuffer Mode

Discussion in 'Particle System Previews' started by richardkettlewell, Mar 28, 2018.

  1. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    860
    Peter77, hippocoder and karl_jones like this.
  2. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    24,176
    I'll probably use this for gore too (haven't tested yet) - will it support instanced meshes as well?
     
    karl_jones likes this.
  3. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    860
    Yes :)
     
    hippocoder likes this.
  4. ifurkend

    ifurkend

    Joined:
    Sep 4, 2012
    Posts:
    346
    Haven’t tried the alpha build yet, but I assume once the total particle count reaches the max particles threshold, the oldest particle is killed instantly. I hope there is an additional option which does a lerp of size or alpha to fade out the particle before killing it. This could justify a new module for ring buffer with the added properties.
     
    hippocoder likes this.
  5. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    3,014
    Hi Richard,

    thank you for implementing the ring buffer suggestion, this is just great! I tested the two ring buffer modes today, but they seem to behave unexpected. Please see the video below.


    I submitted the following bug-report, that contains the sample project shown in the video, which you could use to reproduce the issue:
    (Case 1020633) ParticleSystem: Ring Buffer Mode

    Richard wrote in this post there is such mode, I assume it's the "LoopUntiReplaced" mode.
     
    Last edited: Jan 5, 2019
    richardkettlewell likes this.
  6. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    860
    Hey thanks for trying this out!

    I’m sorry it seems so broken in your test cases!! :( admittedly I only gave it a small amount of testing and it hasn’t had any proper QA time yet, but it seemed functional, so I thought it would be useful to check it met your expectations for such a feature. However it looks quite fundamentally broken in your tests, which I can only apologise for!

    I’ll take a look at your bug report and see where I’ve gone wrong!

    I’ll let you know what I find out.
     
    Peter77 likes this.
  7. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    3,014
    No problem! Software development is complex and I might just have used it in a way you didn't test or think of, this stuff happens. Perhaps it's a particle system setup issue on my end, I don't know.

    Great, looking forward to give it another try :)
     
  8. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    860
    Ahh, had a quick look and it's not as bad as I thought! Yep you used it in a way I didn't do in my testing.. you're calling Play on an already-playing system. This is totally fine, and should be ignored, but I was accidentally resetting my ringbuffer tracking, when this happened.

    I've fixed it, but you could also work around it by only calling Play if the system isnt already playing.
     
    Peter77 likes this.
  9. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    3,014
    You're on fire! :)

    My approach to spawn/emit those footprints is to have a ParticleSystem that is set up using the "Burst Mode" to emit a single particle only, which represents the footprint. Every time the game logic detects a step has been made, it triggers all sorts of feedback, such as logical noise to attract enemies, a sound, the footprint particle, etc. The footprint is the simplest effect though.

    I found using this setup (Burst mode and ParticleSystem.Play) to be the most "artist friendly approach", as it's really playing the ParticleSystem as designed. In an earlier iteration, I was emitting the particle myself, using ParticleSystem.Emit and iterating over the burst entries, but as particle effects got more complex (think of bullet impacts with various sub effects, different timings, etc), this tended to become quite cumbersome to maintain. The solution in this case was simply to use "Play", which worked wonderfully.

    Using this setup and ParticleSystem.Play will continue to work, right?
     
    richardkettlewell likes this.
  10. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    860
    Yep your setup sounds absolutely fine, it simply exposed a bug in this prototype.

    The fix was very simple.. I’ll push out a new version in a few days. I’d like to get some internal testing done on it too before I do an updated build, just in case anything else is lurking :)

    Is the “loop until replaced” mode a useful approximation of what you were asking for in your original request? I know it’s not per-curve, but hopefully it provides something useful that we can offer quickly, whereas the per-curve thing is a much bigger task.
     
  11. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    860
  12. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    860
    This is confirmed for official release in Unity 2018.3! Thanks for the feedback everyone!
     
    Rowlan, hippocoder and Peter77 like this.
  13. Peter77

    Peter77

    Joined:
    Jun 12, 2013
    Posts:
    3,014
    Thank you for adding the feature and sorry for not providing more feedback. I didn't have much time and installing custom Unity builds for one specific feature only don't make it easier.

    I'm glad the feature is officially confirmed now! A few days ago, I also watched the following Unite talk where Karl explains the RingBuffer mode (starts at 1:53min) :)

     
    richardkettlewell likes this.
  14. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    24,176
    That's footsteps, bullet holes, bullets, and all repetitive things sorted!
     
    richardkettlewell likes this.
  15. Shorely

    Shorely

    Joined:
    Dec 17, 2018
    Posts:
    96
    How do I use a Ring Buffer mode like oldest note = stolen notes in audio polyphony?

    ie: When 192 is the maximum number of particles, and they are all already on the screen, but I need to emit more particles, the oldest of the 192 particles is "killed" and recycled to be spat out by the emitter as "new" particles. And so on and so forth.

    In the words of Shrek's anti-hero Lord Farquaad: "Some of you may die, but it's a sacrifice I'm willing to make".
     
  16. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    860
    In Unity 2018.3, in the main settings at the top of the Particle System Component, there is an option called Ring Buffer Mode. Set it to Pause Until Replaced. Then Set Max Particles (in the same area of settings) to 192.

    Finally, emit particles as you wish, using the Emission Module, or script.
     
    Peter77 likes this.
  17. Shorely

    Shorely

    Joined:
    Dec 17, 2018
    Posts:
    96

    Cheers.

    I'd never have guessed this to be polyphonic recycling from the manner it's expressed in the docs:

    Pauses old particles at the end of their lifetime until the Max Particle limit is reached, at which point the system replaces them with new particles..

    That might need a rethink. And there's a double period at the end that doesn't seem right..

    And the use of "replaces" is confusingly off. "recycles" I hope is the right word for this, along with an un-pausing. But I'm not sure that's what is happening. Is there anyway I can know for sure that this doesn't allocate memory through the creation of new particles if I abuse this limit for minutes at a time?
     
  18. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    24,176
    Seems a bit meandering instead of diamond clarity, I agree :p
     
    Shorely likes this.
  19. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    860
    The profiler includes a per-asset memory breakdown.
     

    Attached Files:

  20. Shorely

    Shorely

    Joined:
    Dec 17, 2018
    Posts:
    96
    Not in that sense.

    I mean, from reading the descriptions of ring buffer modes and how they work, is there a way I could discern that this is a limited number of particle objects being recycled?

    I see it as pausing and then DESTROYING particles and creating new ones on demand, which are replacing (and using up new memory), based on the words used to describe it.

    Please look at this wording, from the description:

    Pauses old particles at the end of their lifetime until the Max Particle limit is reached, at which point the system replaces them with new particles..

    I read through all the ring buffer modes and their descriptions multiple times, I watched all the videos I could find about it. There was no point where I went "Aha... this is what I'm looking for, an infinitely recycling particle system that recycles the oldest particle each time!"

    ie a particle system that creates a set number of particles at scene start, allocating all the memory it needs before the level begins, and never exceeds that amount of particles and recycles oldest first, thereby never needing to garbage collect or allocate new memory for new particles.

    The type of system ideal for mobile effects generation.
     
  21. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    860
    If memory allocations are your worry, maybe this will help.

    Firstly, garbage - there is never any garbage. The code is not script, it's native C++, there is no garbage or garbage collection, ever, memory is allocated and freed manually. Garbage [collection] is a side-effect of automatic memory cleanup in managed programming languages such as C#.

    Next, forget about ringbuffer mode for a minute. We'll come back to it.

    When any system begins to play, we make our "best guess" at how much memory is needed for the particles (how many could possibly be alive at the same time?) and make 1 allocation for them. When particles are actually born, we grab them from this buffer, and return them when they die. This is done in O(1) time with no underlying memory allocations. We own the buffer, the entire time.

    If our guess was wrong (it can be wrong if user emits extra from script, for example, then we will increase our max buffer. We do this in chunks of 32, to minimise how many memory requests we are making.

    We never return memory to the memory manager during playback. If you emit 1000 particles, they die, then you emit another 1000, we don't give the memory back in between. We only give it back when the system is stopped.

    Back to ringbuffer mode - if your emission is from script, or over distance, then you'll perhaps have realised that indeed we can't predict the max usage, so there will be a few memory allocations as the particle count increases towards the max. But once it reaches the maximum, there will not be any further allocations.

    Which raises a question - maybe ringbuffer mode should cause the "best guess" code to simply pre-allocate the Max Particles amount? (thoughts welcome)

    For now at least, you could probably work around it by calling Emit(myMaxCount) followed by SetParticles with an empty array, to force 1 allocation for all the particles you could ever have.

    Beyond what I've already shown you (the asset memory profiler stuff in my last post) there is no way that I know of to know that it's the same memory being recycled. You either trust what I'm telling you, or you don't ;)
     
  22. Shorely

    Shorely

    Joined:
    Dec 17, 2018
    Posts:
    96
    Thank you very much for this insight and wisdom!

    I think the biggest problem is that there's not a ring buffer mode that is exactly a fixed polyphony of particles with first note created = first note stolen when polyphony limit reached.

    It seems that all the ring buffer modes attempt to create sufficient particles for demand, regardless of any user set limits to the number of particles... or stop emitting when the particle count limit is hit in terms of currently active particles.

    Have I got this right?

    If you're tired of the polyphony analogy, I apologise. It is the closest I know to this problem, and a very commonly used method of dealing with it. ie. Limited resources and the desire to maintain audience suspension of belief, etc.

    The slang is "note stealing", as the first note of192 played (and still playing) is "stolen" to play the 193rd note, and so on.

    You might initially think that's a lot of polyphony and two hands on an 88 note keyboard couldn't get there, but fast music, with long sustains, releases and delays/effects can see this limit getting hit often. So there's sometimes a bit of "intelligence" applied to which notes are stolen, too. Loudness and pitch being two that might be thought of as analogous to size and opacity in particles.

    Particles might also have made their way off screen, or otherwise obscured, or have a shorter lifespan than others and and be closer to the end of their life, and therefore ripe for theft/re-pooling.

    I'd really like a note stealing, hard cap on the number of particles, with pooling-like, polyphony note stealing style behaviour. ie. if I say a limit of 500 particles, and want pooling/polyphony limiting on, the system steals the particles closest to their natural death, and re-uses them as new releases.
     
  23. Shorely

    Shorely

    Joined:
    Dec 17, 2018
    Posts:
    96
    To put this another way:

    is there a ring buffer mode that acts like object pooling with a hard limit to the number of particles, that steals from oldest living particles when the pool is empty, thereby treating all particles as pooled, regardless of their current state.

    I thought there was, but now I'm not so sure.
     
  24. richardkettlewell

    richardkettlewell

    Unity Technologies

    Joined:
    Sep 9, 2015
    Posts:
    860
    Yes that is ring buffer with mode set to Pause until Replaced :)
     
    Shorely likes this.
  25. Shorely

    Shorely

    Joined:
    Dec 17, 2018
    Posts:
    96
    I think these modes deserve a naming convention indicative of how they work rather than one of each of the ways they might be used. Examples of their use could be explained with those... examples.

    Naming for this mode might better be: hardLimit_hold