John
John

Reputation: 151

Unity: Change Particle System to pooling

I'm trying to change my particle system function to a pooling instead of instantiating everytime. I want to reuse the particles. How is that possible? I have no idea how to start although i watched the unity tutorial but somehow it's still unclear. maybe because im calling the particle system function in other classes it's confusing me somehow.

public ParticleSystem[] Myeffects;


public void Particle(int particleNum, Vector3 Pos)
{
    if (Myeffects != null && Myeffects[particleNumber] != null )
    {
        if (Myeffects[particleNumber].isPlaying)
            Myeffects[particleNumber].Stop();

        ParticleSystem temp = Instantiate(Myeffects[particleNum], particlePos, new Quaternion()) as ParticleSystem;

        temp.Play();
    }
}
}

Upvotes: 3

Views: 6167

Answers (1)

Programmer
Programmer

Reputation: 125315

First of all, Select your Particle System prefab/TNT then make sure that Play On Awake is unchecked. The pooling script below is dedicated tricky way to accomplish that. It will create an array of ParticleSystem specified then re-use them. Notice that ParticlePool does not inherit from MonoBehaviour, so make sure to copy it directly.

using UnityEngine;
using System.Collections;
using System;

public class ParticlePool
{
    int particleAmount;
    ParticleSystem[] NormalParticle;
    ParticleSystem[] TNTParticle;

    public ParticlePool(ParticleSystem normalPartPrefab, ParticleSystem tntPartPrefab, int amount = 10)
    {
        particleAmount = amount;
        NormalParticle = new ParticleSystem[particleAmount];
        TNTParticle = new ParticleSystem[particleAmount];

        for (int i = 0; i < particleAmount; i++)
        {
            //Instantiate 10 NormalParticle
            NormalParticle[i] = GameObject.Instantiate(normalPartPrefab, new Vector3(0, 0, 0), new Quaternion()) as ParticleSystem;

            //Instantiate 10 TNTParticle
            TNTParticle[i] = GameObject.Instantiate(tntPartPrefab, new Vector3(0, 0, 0), new Quaternion()) as ParticleSystem;
        }
    }

    //Returns available GameObject
    public ParticleSystem getAvailabeParticle(int particleType)
    {
        ParticleSystem firstObject = null;

        //Normal crate
        if (particleType == 0)
        {
            //Get the first GameObject
            firstObject = NormalParticle[0];
            //Move everything Up by one
            shiftUp(0);
        }

        //TNT crate
        else if (particleType == 1)
        {
            //Get the first GameObject
            firstObject = TNTParticle[0];
            //Move everything Up by one
            shiftUp(1);
        }

        return firstObject;
    }

    //Returns How much GameObject in the Array
    public int getAmount()
    {
        return particleAmount;
    }

    //Moves the GameObject Up by 1 and moves the first one to the last one
    private void shiftUp(int particleType)
    {
        //Get first GameObject
        ParticleSystem firstObject;

        //Normal crate
        if (particleType == 0)
        {
            firstObject = NormalParticle[0];
            //Shift the GameObjects Up by 1
            Array.Copy(NormalParticle, 1, NormalParticle, 0, NormalParticle.Length - 1);

            //(First one is left out)Now Put first GameObject to the Last one
            NormalParticle[NormalParticle.Length - 1] = firstObject;
        }

        //TNT crate
        else if (particleType == 1)
        {
            firstObject = TNTParticle[0];
            //Shift the GameObjects Up by 1
            Array.Copy(TNTParticle, 1, TNTParticle, 0, TNTParticle.Length - 1);

            //(First one is left out)Now Put first GameObject to the Last one
            TNTParticle[TNTParticle.Length - 1] = firstObject;
        }
    }
}

Then, your ParticleHolder script should be updated with the code below. That's it. No more instantiation.

public class ParticleHolder : MonoBehaviour
{

    public ParticleSystem[] effects;
    ParticlePool particlePool;

    void Start()
    {
        // 0 = Normal crate
        // 1 = TNT crate
        particlePool = new ParticlePool(effects[0], effects[1], 5);
    }

    public void playParticle(int particleType, Vector3 particlePos)
    {
        ParticleSystem particleToPlay = particlePool.getAvailabeParticle(particleType);

        if (particleToPlay != null)
        {
            if (particleToPlay.isPlaying)
                particleToPlay.Stop();

            particleToPlay.transform.position = particlePos;
            particleToPlay.Play();
        }

    }
}

Upvotes: 3

Related Questions