0
\$\begingroup\$

I have a particle system based on this answer to another question about manually placing particles (no movement). However, it's very costly to run Emit() after placing each particle via emitparams. I've written an alternate method that assigns the various positions to the particles themselves using Particle.position and then calls Emit() only once after the whole cloud is constructed. It does perform much faster, but all the particles end up at 0,0,0 instead of their respective positions. I've logged out their positions to make sure they are correct and they are, but I'm not sure why this method is not working.

How do I set the positions of individual particles correctly using Particle.position?

I am rendering many particle systems and around 5-6k particles at a time, so I need a more performant method than one at a time via emitparams.

I've made a quick sandbox script of the problem below. The old, inefficient but working method in the script below is ParticleCloudMakerMethod2(). The new, more performant method that doesn't yet render the positions correctly is ParticleCloudMakerMethod1(). How do I fix the incorrect particle positions produced by ParticleCloudMakerMethod1()?

using UnityEngine;
using Random = UnityEngine.Random;

[RequireComponent(typeof(ParticleSystem))]
public class ParticleCloudRandomizer : MonoBehaviour {

    public float radius = 1f;
    ParticleSystem _particleSystem;
    private ParticleSystem.Particle[] _particles;
    private ParticleSystem.EmitParams _emitParams;

    void Start () {
        _particleSystem = GetComponent<ParticleSystem>();
        _emitParams = new ParticleSystem.EmitParams();
        _particles = new ParticleSystem.Particle[_particleSystem.maxParticles];
        
        ParticleCloudMakerMethod1();
        //ParticleCloudMakerMethod2();
    }
    
    /* This method is MORE efficient because it calls Emit() is called only once, but neither the position nor the
     startLifetime are being set - all particles end up at 0,0,0 */
    void ParticleCloudMakerMethod1()
    {
        _particleSystem.GetParticles(_particles);
        
        for(int i = 0; i < _particles.Length; i++)
        {
            _particles[i].position = Random.insideUnitSphere * radius;
            _particles[i].startLifetime = float.MaxValue;
        }
        
        _particleSystem.SetParticles(_particles, _particles.Length);
        _particleSystem.Emit(_particles.Length);
        _particleSystem.Play();
    }

    /* This method is LESS efficient because it calls Emit() is called once per particle, but both position
     and lifetime are set correctly */
    void ParticleCloudMakerMethod2()
    {
        _particleSystem.GetParticles(_particles);
        
        for(int i = 0; i < _particles.Length; i++)
        {
            _emitParams.position = Random.insideUnitSphere * radius;
            _emitParams.startLifetime = float.MaxValue;
            _particleSystem.Emit(_emitParams, 1);
        }
        
        _particleSystem.Play();
    }
}

Note: The particle system I'm using has looping off and play on awake off and is only using the renderer.

\$\endgroup\$
2
  • \$\begingroup\$ When I've done this in the past, I have not called Emit at all, but just left the particles where I set them instead of asking them to be re-emitted. \$\endgroup\$
    – DMGregory
    Jun 11, 2021 at 15:36
  • \$\begingroup\$ @DMGregory - thanks for taking a look! I tried skipping Emit and my shapes stopped rendering at all. Any thoughts on how to fix the positions problem with CreateParticles()? That baffles me - it should be working. \$\endgroup\$
    – gromiczek
    Jun 11, 2021 at 20:32

0

You must log in to answer this question.

Browse other questions tagged .