Search Unity

[Solved] Help, need game objects to destroy offscreen c#

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

  1. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Hello, unity community we have a problem where the Instanced gameobjects from our spawner, disappear while on screen. I did try to change the destroy time to a higher number so they have time to leave the screen. What I think is happening is that an object gets spawned leaves the screen, than another one is spawned and moves into the screen. Then it turns off all game objects of that name, including the ones from the set that's still on the screen. can we get any advice? do any of you know what should do? hope to hear from you soon thanks :).

    Destroy script(Note; this ties into a object pool):

    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.         NewObjectPool.instance.PoolObject (this.gameObject);
    16.     }
    17. }
    18.  
    Spawner Script:

    Code (CSharp):
    1. using 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. }
     
  2. tedthebug

    tedthebug

    Joined:
    May 6, 2015
    Posts:
    2,570
    i haven't gotten around to doing pooling yet (it's on my list) but I put the destroy onto the script that attaches to the enemy prefab so it only ever relates to that one enemy. Is that where your destroy script is attached?
     
  3. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    I wonder if it's invoking the object.Destroy(), not your local MonoBehaviour Destory(). Try renaming the function as a test.
     
    Kiwasi likes this.
  4. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,261
    You can avoid all this by using this

    Code (CSharp):
    1. void OnBecameInvisible()
    2. {
    3.     NewObjectPool.instance.PoolObject (this.gameObject);
    4. }
    This will cause it to be pooled once the object is not seen by ANY camera including the scene view camera.

    As for it turning off all the objects of the same name, we need to see what's happening in the pooling code.
     
  5. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Thanks everyone thus far who has tried to help. Still attempting to fix the problem.

    Yes, my destroy script is on the enemy.

    Tried this and nothing changed.

    Chris, I got an error when I tried this it conflicting with line 123 on my object pooler script.



    Also, the only thing I'm worried about with this script is that the object don't automatically get added back to the object pooler's list until is spawned again. Therefore I have a bunch of active game objects floating offscreen until they are called again. Which would take up more memory with rendering and animation etc... thats why we were trying to use the destroy script in the first place.

    Object pooler script:

    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. }
     
  6. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,261
    The object is getting destroyed some how.

    Remove all the code you have for returning the object to the pool and only use the OnBecameInvisible() to do it and see if that helps.

    I'm going to take a look at my object pool system and see if there is something that I'm doing that might be different. Your pooling system looks a lot like the one I have, don't remember where I found it, but I've made quite a few modifications. I also have seen those errors using it before.
     
  7. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,261
    Okay, I've looked at my code and compared to your code. The changes I've made are mostly for ease of use and making it GC friendly, which is one reason you would want to pool in the first place.

    I use compareTag and not name to do the match, using name generates garbage.
    I use a Queue instead of a List so I can enqueue and dequeue objects, makes no real difference, maybe a little cleaner code wise.
    I use SetActive and not SetActiveRecursively and I do it after adding it to the pool container which, I think is how I fixed the errors when I got them. Set the parent first then deactivate see it that helps.
     
  8. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    Thanks for the advice I did try my best to do what you suggested, same errors. However, I'm not quite sure about how to implement some of your suggestions. Can you give more specific instructions?
     
  9. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,261
    What does your object code look like now?
     
  10. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    While, I didn't change the object pooler script at all. Because i didn't understand, so thats the same.

    But, this is all I have for the destroy script:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DestoryOverTime : MonoBehaviour {
    5.  
    6.     void Update ()
    7.     {
    8.         NewObjectPool.instance.PoolObject (this.gameObject);
    9.     }
    10. }
     
  11. clearrose

    clearrose

    Joined:
    Oct 24, 2012
    Posts:
    349
    OK, thanks allot everyone, especially you Chris. We finally got it to work correctly, if any one wants I can post the final code later. I don't have it in front of me at the moment.