Search Issue Tracker
Won't Fix
Votes
0
Found in
2019.4
2019.4.31f1
2020.3
2021.2
2022.1
Issue ID
1383668
Regression
No
Wrong Particle is replaced by Ring Buffer Mode when a specific Particle is removed via script and Max Particles are exceeded
How to reproduce:
1. Open the user-submitted project
2. Open the scene "TestScene" (Assets/TestScene.unity)
3. In the Hierarchy window, select the GameObject "Particles"
4. In the Inspector window, under the script "Test", press the button "Emit particle" 7 times
5. Under "Clear at index:", press the button "0"
6. Press "Emit particle" 2 more times
7. Inspect the Scene view
Expected result: Final particle was spawned at index 0 of the Particles array
Actual result: Final particle was spawned at index 3 of the Particles array
Reproducible with: 2019.4.34f1, 2020.3.24f1, 2021.2.6f1, 2022.1.0b2
-
Grosnus
Jan 22, 2022 06:06
My response to the resolution note:
Thank you for examining this problem. To quickly explain my use case: I was making a dynamic decal system where each decal is placed at precise position determined by whatever caused the decal to spawn. System assumes each decal can have different parameters such as lifetime, color, position, size etc. If maximum amount of decals is reached then oldest decal is replaced by newly emitted one.
I decided to go with ParticleSystem because it handles a lot of things for me already such as z-sorting (even if multiple particles overlap on the same plane), batched mesh creation with customized attributes, fading, ring buffer and a lot more. From experience I know that often recreating such systems in managed code can lead to worse performance than Unity's internal systems so I tried to utilize ParticleSystem functionality as much as possible.
I was afraid that because in my case a lot of particles can be spawned at quick succession invoking .SetParticles over and over will create unnecessary overhead and decided to limit usage of that method to only removal of particles, which doesn't need to happen real-time.
The reason I wanted to remove particles in the first place is because after particles reach their lifetime they will not remove themselves from system because of ring buffer mode. That might be by design, however that is also causing ParticleSystem's culling not to properly cull the particles, because technically they still exist and they influence the bounding box, which now might be a lot bigger than it could be.
The other problem I had was that I needed to know the last index of the particle that was just emitted because I was using SetCustomParticleData to set additional parameters per particle after emission. I was also keeping my own array of data per particle that needed to exactly reflect ParticleSystem's array.
Knowing the issues beforehand I might've considered different solution (no ring buffer and manual control for example) however I ultimately found a workaround for the last index problem by studying when and why a particular index is being replaced and with some bookkeeping I was able to create a method that predicts last index in all cases, even after removing particles via SetParticles.
I will email another example project that will show how I did that in case it's at all helpful.
Add comment
All about bugs
View bugs we have successfully reproduced, and vote for the bugs you want to see fixed most urgently.
Latest issues
- Articulation Body with 'Revolute' Joint Type has erratic behavior when Upper Limit is set to above 360
- WebGL Player fails to render Scene when Terrain with Detail Mesh is added and WebGPU Graphics API is used
- Inconsistent errors are logged when different types are passed into the Query "Q<>" method in UIToolkit and the ancestor VisualElement is null
- Crash on GetMaterialPropertyByIndex when opening a specific Scene
- Discrepancies in the styling are present when using a TSS file instead of a USS file in custom EditorWindow
Resolution Note:
I've looked into this, but it's really unclear how to properly support removing particles via SetParticles when using ring buffer mode. This mode assumes to have full control over the particles array and makes assumptions about the layout, which can be violated if removing particles via SetParticles.
As your system looks highly customised, would it be simpler to not use the ring buffer mode, and fully control a small list of particles via script? (Instead of calling Emit + ringbuffer mode, manipulate your own particles array to get the behaviour you want?) Then just use the Particle System for the rendering.