[Solved] Game object not being added back to Object pool c#

We are having a problem where our object pool isn’t adding the object back into the list, after the object goes inactive offscreen. Note, that the object pool removes an object from the list when it becomes active and is spawned, it’s supposed to added back for reuse.

Plz, help us figure this out.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class NewObjectPool : MonoBehaviour {
   
    public static NewObjectPool instance;
   
    /// <summary>
    /// The object prefabs which the pool can handle.
    /// </summary>
    public GameObject[] objectPrefabs;
   
    /// <summary>
    /// The pooled objects currently available.
    /// </summary>
    public List<GameObject>[] pooledObjects;
   
    /// <summary>
    /// The amount of objects of each type to buffer.
    /// </summary>
    public int[] amountToBuffer;
   
    public int defaultBufferAmount = 3;
   
    /// <summary>
    /// The container object that we will keep unused pooled objects so we dont clog up the editor with objects.
    /// </summary>
    protected GameObject containerObject;
   
    void Awake ()
    {
        instance = this;
    }
   
    // Use this for initialization
    void Start ()
    {
        containerObject = new GameObject("ObjectPool");
       
        //Loop through the object prefabs and make a new list for each one.
        //We do this because the pool can only support prefabs set to it in the editor,
        //so we can assume the lists of pooled objects are in the same order as object prefabs in the array
        pooledObjects = new List<GameObject>[objectPrefabs.Length];
       
        int i = 0;
        foreach ( GameObject objectPrefab in objectPrefabs )
        {
            pooledObjects[i] = new List<GameObject>();
           
            int bufferAmount;
           
            if(i < amountToBuffer.Length) bufferAmount = amountToBuffer[i];
            else
                bufferAmount = defaultBufferAmount;
           
            for ( int n=0; n<bufferAmount; n++)
            {
                GameObject newObj = Instantiate(objectPrefab) as GameObject;
                newObj.name = objectPrefab.name;
                PoolObject(newObj);
            }
           
            i++;
        }
    }
   
    /// <summary>
    /// Gets a new object for the name type provided.  If no object type exists or if onlypooled is true and there is no objects of that type in the pool
    /// then null will be returned.
    /// </summary>
    /// <returns>
    /// The object for type.
    /// </returns>
    /// <param name='objectType'>
    /// Object type.
    /// </param>
    /// <param name='onlyPooled'>
    /// If true, it will only return an object if there is one currently pooled.
    /// </param>
    public GameObject GetObjectForType ( string objectType , bool onlyPooled )
    {
        for(int i=0; i<objectPrefabs.Length; i++)
        {
            GameObject prefab = objectPrefabs[i];
            if(prefab.name == objectType)
            {
               
                if(pooledObjects[i].Count > 0)
                {
                    GameObject pooledObject = pooledObjects[i][0];
                    pooledObjects[i].RemoveAt(0);
                    pooledObject.transform.parent = null;
                    pooledObject.SetActiveRecursively(true);
                   
                    return pooledObject;
                   
                } else if(!onlyPooled) {
                    return Instantiate(objectPrefabs[i]) as GameObject;
                }
               
                break;
               
            }
        }
       
        //If we have gotten here either there was no object of the specified type or non were left in the pool with onlyPooled set to true
        return null;
    }
   
    /// <summary>
    /// Pools the object specified.  Will not be pooled if there is no prefab of that type.
    /// </summary>
    /// <param name='obj'>
    /// Object to be pooled.
    /// </param>
    public void PoolObject ( GameObject obj )
    {
        for ( int i=0; i<objectPrefabs.Length; i++)
        {
            if(objectPrefabs[i].name == obj.name)
            {
                obj.SetActiveRecursively(false);
                obj.transform.parent = containerObject.transform;
                pooledObjects[i].Add(obj);
                return;
            }
        }
    }
   
}

You are doing a name comparison. It’s not appending clone or anything?

Nope, no clones. What do you think it could be?

Anyone else have any advice?

Where is PoolObject() being called from? By “inactive” do you mean you’re disabling the GOs? If you disable it, none of the scripts on it will keep running (including their Update methods) so you can’t expect them to re-pool themselves.

Yes, we were disabling the game objects, with this script:

using UnityEngine;
using System.Collections;

public class DestoryOverTime : MonoBehaviour {

    public float DestoryTime = 25f;

    void OnEnable()
    {
        Invoke ("Destroy", DestoryTime);
    }

    void Destroy()
    {
        gameObject.SetActive (false);
    }
}

At first even before adding the disable script the objects remained active and still didn’t repool themselves.

The PoolObject is being called here, in the spawner script on line 42:

sing UnityEngine;
using System.Collections;

public class Spawner : MonoBehaviour {
  
        public GameObject Instance;                // The enemy prefab to be spawned.
        public float maxtime = 25;           // How long between each spawn.
        public float mintime = 10;

        //current time
        private float time;
      
        //The time to spawn the object
        private float spawnTime;
  
        public Transform[] spawnPoints;         // An array of the spawn points this enemy can spawn from.

        void Start ()
        {
            SetRandomTime();
            time = mintime;

        }

        void FixedUpdate(){
      
            //Counts up
            time += Time.deltaTime;
          
            //Check if its the right time to spawn the object
            if(time >= spawnTime){
                Spawn();
                SetRandomTime();
        }
      
    }
      
        void Spawn ()
        {
            time = 0;

            GameObject obj = NewObjectPool.instance.GetObjectForType("Orange Fish", true);
            if (obj == null) return;

            obj.transform.position = transform.position;
            obj.transform.rotation = transform.rotation;
            obj.SetActive (true);

        }

    //Sets the random time between minTime and maxTime

    void SetRandomTime(){
        spawnTime = Random.Range(mintime, maxtime);
    }
}

Where do the object go back into the pool once you’re finished with them?

On quick glance, it looks like you’re missing a call to PoolObject() in the Destroy() function, to put the gameobject back into the pool.

Oh, thanks how, would that be written in c#?

void Destroy()
{
  NewObjectPool.instance.PoolObject (this.gameObject);
  //gameObject.SetActive (false); //PoolObject already sets everything to false
}

Btw i haven’t tested this

1 Like

Thank you very much, happy, happy joy, joy !!