Search Unity

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

Discussion in 'Scripting' started by clearrose, Jul 28, 2015.

  1. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    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.




    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class NewObjectPool : MonoBehaviour {
    6.    
    7.     public static NewObjectPool instance;
    8.    
    9.     /// <summary>
    10.     /// The object prefabs which the pool can handle.
    11.     /// </summary>
    12.     public GameObject[] objectPrefabs;
    13.    
    14.     /// <summary>
    15.     /// The pooled objects currently available.
    16.     /// </summary>
    17.     public List<GameObject>[] pooledObjects;
    18.    
    19.     /// <summary>
    20.     /// The amount of objects of each type to buffer.
    21.     /// </summary>
    22.     public int[] amountToBuffer;
    23.    
    24.     public int defaultBufferAmount = 3;
    25.    
    26.     /// <summary>
    27.     /// The container object that we will keep unused pooled objects so we dont clog up the editor with objects.
    28.     /// </summary>
    29.     protected GameObject containerObject;
    30.    
    31.     void Awake ()
    32.     {
    33.         instance = this;
    34.     }
    35.    
    36.     // Use this for initialization
    37.     void Start ()
    38.     {
    39.         containerObject = new GameObject("ObjectPool");
    40.        
    41.         //Loop through the object prefabs and make a new list for each one.
    42.         //We do this because the pool can only support prefabs set to it in the editor,
    43.         //so we can assume the lists of pooled objects are in the same order as object prefabs in the array
    44.         pooledObjects = new List<GameObject>[objectPrefabs.Length];
    45.        
    46.         int i = 0;
    47.         foreach ( GameObject objectPrefab in objectPrefabs )
    48.         {
    49.             pooledObjects[i] = new List<GameObject>();
    50.            
    51.             int bufferAmount;
    52.            
    53.             if(i < amountToBuffer.Length) bufferAmount = amountToBuffer[i];
    54.             else
    55.                 bufferAmount = defaultBufferAmount;
    56.            
    57.             for ( int n=0; n<bufferAmount; n++)
    58.             {
    59.                 GameObject newObj = Instantiate(objectPrefab) as GameObject;
    60.                 newObj.name = objectPrefab.name;
    61.                 PoolObject(newObj);
    62.             }
    63.            
    64.             i++;
    65.         }
    66.     }
    67.    
    68.     /// <summary>
    69.     /// 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
    70.     /// then null will be returned.
    71.     /// </summary>
    72.     /// <returns>
    73.     /// The object for type.
    74.     /// </returns>
    75.     /// <param name='objectType'>
    76.     /// Object type.
    77.     /// </param>
    78.     /// <param name='onlyPooled'>
    79.     /// If true, it will only return an object if there is one currently pooled.
    80.     /// </param>
    81.     public GameObject GetObjectForType ( string objectType , bool onlyPooled )
    82.     {
    83.         for(int i=0; i<objectPrefabs.Length; i++)
    84.         {
    85.             GameObject prefab = objectPrefabs[i];
    86.             if(prefab.name == objectType)
    87.             {
    88.                
    89.                 if(pooledObjects[i].Count > 0)
    90.                 {
    91.                     GameObject pooledObject = pooledObjects[i][0];
    92.                     pooledObjects[i].RemoveAt(0);
    93.                     pooledObject.transform.parent = null;
    94.                     pooledObject.SetActiveRecursively(true);
    95.                    
    96.                     return pooledObject;
    97.                    
    98.                 } else if(!onlyPooled) {
    99.                     return Instantiate(objectPrefabs[i]) as GameObject;
    100.                 }
    101.                
    102.                 break;
    103.                
    104.             }
    105.         }
    106.        
    107.         //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
    108.         return null;
    109.     }
    110.    
    111.     /// <summary>
    112.     /// Pools the object specified.  Will not be pooled if there is no prefab of that type.
    113.     /// </summary>
    114.     /// <param name='obj'>
    115.     /// Object to be pooled.
    116.     /// </param>
    117.     public void PoolObject ( GameObject obj )
    118.     {
    119.         for ( int i=0; i<objectPrefabs.Length; i++)
    120.         {
    121.             if(objectPrefabs[i].name == obj.name)
    122.             {
    123.                 obj.SetActiveRecursively(false);
    124.                 obj.transform.parent = containerObject.transform;
    125.                 pooledObjects[i].Add(obj);
    126.                 return;
    127.             }
    128.         }
    129.     }
    130.    
    131. }
    132.  
     
  2. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    You are doing a name comparison. It's not appending clone or anything?
     
  3. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Nope, no clones. What do you think it could be?

     
  4. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Anyone else have any advice?
     
  5. DonLoquacious

    DonLoquacious

    Joined:
    Feb 24, 2013
    Posts:
    1,667
    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.
     
  6. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349


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

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DestoryOverTime : MonoBehaviour {
    5.  
    6.     public float DestoryTime = 25f;
    7.  
    8.     void OnEnable()
    9.     {
    10.         Invoke ("Destroy", DestoryTime);
    11.     }
    12.  
    13.     void Destroy()
    14.     {
    15.         gameObject.SetActive (false);
    16.     }
    17. }
    18.  
    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:

    Code (CSharp):
    1. sing UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Spawner : MonoBehaviour {
    5.  
    6.         public GameObject Instance;                // The enemy prefab to be spawned.
    7.         public float maxtime = 25;           // How long between each spawn.
    8.         public float mintime = 10;
    9.  
    10.         //current time
    11.         private float time;
    12.      
    13.         //The time to spawn the object
    14.         private float spawnTime;
    15.  
    16.         public Transform[] spawnPoints;         // An array of the spawn points this enemy can spawn from.
    17.  
    18.         void Start ()
    19.         {
    20.             SetRandomTime();
    21.             time = mintime;
    22.  
    23.         }
    24.  
    25.         void FixedUpdate(){
    26.      
    27.             //Counts up
    28.             time += Time.deltaTime;
    29.          
    30.             //Check if its the right time to spawn the object
    31.             if(time >= spawnTime){
    32.                 Spawn();
    33.                 SetRandomTime();
    34.         }
    35.      
    36.     }
    37.      
    38.         void Spawn ()
    39.         {
    40.             time = 0;
    41.  
    42.             GameObject obj = NewObjectPool.instance.GetObjectForType("Orange Fish", true);
    43.             if (obj == null) return;
    44.  
    45.             obj.transform.position = transform.position;
    46.             obj.transform.rotation = transform.rotation;
    47.             obj.SetActive (true);
    48.  
    49.         }
    50.  
    51.     //Sets the random time between minTime and maxTime
    52.  
    53.     void SetRandomTime(){
    54.         spawnTime = Random.Range(mintime, maxtime);
    55.     }
    56. }
     
  7. Defero

    Defero

    Joined:
    Jul 9, 2012
    Posts:
    200
    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.
     
  8. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Oh, thanks how, would that be written in c#?
     
  9. Defero

    Defero

    Joined:
    Jul 9, 2012
    Posts:
    200
    Code (CSharp):
    1. void Destroy()
    2. {
    3.   NewObjectPool.instance.PoolObject (this.gameObject);
    4.   //gameObject.SetActive (false); //PoolObject already sets everything to false
    5. }
    Btw i haven't tested this
     
  10. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Thank you very much, happy, happy joy, joy !!