Search Unity

  1. We are looking for feedback on the experimental Unity Safe Mode which is aiming to help you resolve compilation errors faster during project startup.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

How to randomly spawn a gameobject from a list/collection of GameObjects (Object pooled)

Discussion in 'Scripting' started by Sholz, Nov 8, 2017.

  1. Sholz

    Sholz

    Joined:
    Dec 12, 2016
    Posts:
    21
    Please I have been trying to randomly spawn a gameobject from a list/collection of GameObjects implementing Object pooling technique for performance sake.

    This is how far I have gotten:

    http://bit.ly/2yFGhji

    I was advised to implement inheritance..am really stuck.? Thanks



    Code (CSharp):
    1.  
    2.     using System.Collections;
    3.     using System.Collections.Generic;
    4.     using UnityEngine;
    5.  
    6.  
    7.  
    8.     public class ObjectPoolRandomObject : MonoBehaviour {
    9.         private float fireTime = .05f;//start Time of spawning
    10.         [Tooltip("How long The Object will last in the scene eg" +
    11.             "4 lasts 4 sec and 20 lasts 20 in scene Smaller rate for faster bullets. long for lasting vehicles")]
    12.         public float fireRate = 2f; //Smaller rate for faster bullets. long for lasting vehicles
    13.         public GameObject[] pooledObject;
    14.         public int poolAmount = 5;
    15.         List<GameObject> cars;
    16.  
    17.         void Start()
    18.  
    19.         {
    20.  
    21.             bullets = new List<GameObject>();
    22.             for (int i = 0; i < poolAmount; i++)  
    23.  
    24.                 //GameObject obj = (GameObject)Instantiate(car); //POOLED 1 OBJECT (OK)
    25.                 GameObject obj = (GameObject)Instantiate(pooledObject[Random.Range(0, pooledObject.Length)]);
    26.                 obj.SetActive(false);
    27.                 bullets.Add(obj);
    28.             }
    29.             InvokeRepeating("Fire", fireTime, fireRate);
    30.  
    31.         }
    32.  
    33.         void Fire()
    34.  
    35.         {
    36.             for (int i = 0; i < bullets.Count; i++)
    37.  
    38.             {
    39.                 bullets[i].transform.position = transform.position;
    40.                 bullets[i].transform.rotation = transform.rotation;
    41.                 bullets[i].SetActive(true);
    42.                 break;
    43.             }
    44.         }
    45.     }
    46.  
    47.      
    The goal I am getting at is to spawn an infinite loop of cars that would not h performance since Destroy(gameObject) is highly performance on Android and deactivating clones will make it accumulate clones over time..



    Thanks for reading
     
  2. Rabenrecht

    Rabenrecht

    Joined:
    Sep 30, 2017
    Posts:
    8
    Well, first the Random.Range Needs to be set at (0,pooledObject.Length - 1).
    Otherwise you can get IndexOutOfBounds exceptions.

    Sencond, well what does happen when you execute your Code?
     
  3. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,474
    Not required, when you do Random.Range with ints the upper range is exclusive so subtracting 1 would mean it would never choose the last index in your collection.
    https://docs.unity3d.com/ScriptReference/Random.Range.html
     
    KelsoMRK likes this.
  4. Mike-Geig

    Mike-Geig

    Unity Technologies

    Joined:
    Aug 16, 2013
    Posts:
    178
    Try this with your code:

    Code (CSharp):
    1.     using System.Collections;
    2.     using System.Collections.Generic;
    3.     using UnityEngine;
    4.     public class ObjectPoolRandomObject : MonoBehaviour
    5.     {
    6.         private float fireTime = .05f;      //start Time of spawning
    7.         [Tooltip("How long The Object will last in the scene eg 4 lasts 4 sec and 20 lasts 20 in scene Smaller rate for faster bullets. long for lasting vehicles")]
    8.         public float fireRate = 2f;         //Smaller rate for faster bullets. long for lasting vehicles
    9.         public int poolAmount = 5;          //Size of the object pool
    10.         public GameObject[] randomObjects;  //Collection of random game objects to go into pool
    11.  
    12.         List<GameObject> pool;              //Actual pool
    13.         int currentIndex = 0;               //The current index of the pool
    14.         void Start()
    15.         {
    16.             pool = new List<GameObject>();
    17.             for (int i = 0; i < poolAmount; i++)
    18.             {
    19.                 int randomIndex = Random.Range(0, randomObjects.Length);
    20.                 GameObject obj = (GameObject)Instantiate(pooledObject[randomIndex]);
    21.                 obj.SetActive(false);
    22.                 pool.Add(obj);
    23.             }
    24.  
    25.             InvokeRepeating("Fire", fireTime, fireRate);
    26.         }
    27.         void Fire()
    28.         {
    29.             bullets[currentIndex].transform.position = transform.position;
    30.             bullets[currentIndex].transform.rotation = transform.rotation;
    31.             bullets[currentIndex].SetActive(true);
    32.  
    33.             if(++currentIndex > pool.Length)
    34.                 currentIndex = 0;
    35.         }
    36.     }
     
    Sholz likes this.
  5. Sholz

    Sholz

    Joined:
    Dec 12, 2016
    Posts:
    21
    Errrr..I really appreciate you for trying but this didn't work... I guess I may have sacrifice performance and spawn and destroy
     
  6. Mike-Geig

    Mike-Geig

    Unity Technologies

    Joined:
    Aug 16, 2013
    Posts:
    178
    Why don't you take a few minutes to tell us how it didn't work so we can help? This code works, so that means you're doing something other than what it seems like you mentioned. What exactly are you trying to do?
     
    Sholz likes this.
  7. JoeFernaldSG

    JoeFernaldSG

    Joined:
    Apr 3, 2017
    Posts:
    9
    Object pooling is a tried and true method to implement something along these lines in a way that is performant.

    Based on your code I suspect things are working...just not in the way that you thought.

    First thing I'd do would be to do the SetActive() in your fire function first. I'm not 100% sure if a game objects transform can be updated if it's game object is actually disabled so it's worth trying.

    Secondly, there are a number of things that could be causing problems...from the objects having rigid bodies thus gravity applied and vanishing off screen to the transform you used being in view of the camera. I'd set breakpoints in the code and debug what values are being assigned, and I'd also check the unity scene view....Hit pause in the editor after you "fire" choose a game object (which should be in your games heiarchy at runtime) then press F to focus on it... it could be well off screen or out of view of your game camera, or even on the wrong camera layer.
     
  8. Sholz

    Sholz

    Joined:
    Dec 12, 2016
    Posts:
    21
    Last edited: Nov 13, 2017
  9. Mike-Geig

    Mike-Geig

    Unity Technologies

    Joined:
    Aug 16, 2013
    Posts:
    178
    Oh, just change the name "pooled objects" to "randomobjects" and "bullets" to "pool"
     
  10. Sholz

    Sholz

    Joined:
    Dec 12, 2016
    Posts:
    21
    So Moderator...you may mark this as Solved..Thank @mikegeig for the support.

    wouldn't have done this without you

    For fellow newbies.. you may see below...

    it has 2 sections..
    -1st section to be attached to 2 or more diff objects so it will always move...
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Instantiate : MonoBehaviour {
    6.  
    7.     // Use this for initialization
    8.     void Start () {
    9.        
    10.     }
    11.    
    12.     // Update is called once per frame
    13.     void Update () {
    14.         transform.Translate(Vector3.forward);
    15.     }
    16. }
    17.  
    -2nd section ...
    is the real Object Pooled Random spawner...to be added to a seperate emptyGameobject to spawn the above "moving" gameobject
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class ObjectPoolRandomSholaOginni : MonoBehaviour {
    6.  
    7.     private float fireTime = .05f;      //start Time of spawning
    8.     [Tooltip("How long The Object will last in the scene eg 4 lasts 4 sec and 20 lasts 20 in scene Smaller rate for faster bullets. long for lasting vehicles")]
    9.     public float fireRate = 2f;         //Smaller rate for faster bullets. long for lasting vehicles
    10.     public int poolAmount = 5;          //Size of the object pool
    11.     public GameObject[] randomObjects;  //Collection of random game objects to go into pool
    12.     // GameObject[] pool;
    13.     List<GameObject> pool;              //Actual pool
    14.     int currentIndex = 0;               //The current index of the pool
    15.     void Start()
    16.     {
    17.         pool = new List<GameObject>();
    18.         for (int i = 0; i < poolAmount; i++)
    19.         {
    20.             int randomIndex = Random.Range(0, randomObjects.Length);
    21.             GameObject obj = (GameObject)Instantiate(randomObjects[randomIndex]);
    22.             obj.SetActive(false);
    23.             pool.Add(obj);
    24.         }
    25.  
    26.         InvokeRepeating("Fire", fireTime, fireRate);
    27.     }
    28.     void Fire()
    29.     {
    30.         pool[currentIndex].transform.position = transform.position;
    31.         pool[currentIndex].transform.rotation = transform.rotation;
    32.         pool[currentIndex].SetActive(true);
    33.  
    34.         if (++currentIndex >= pool.Count)// last issue
    35.         {
    36.             currentIndex = 0;
    37.             for (int i = 0; i < pool.Count; i++)
    38.             {
    39.                 pool[i].gameObject.SetActive(false);
    40.             }
    41.             // pool[].gameObject.SetActive(false);
    42.         }
    43.     }
    44.  
    45. }
    46.  
     
unityunity