Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

[SOLVED]Disable multiple game objects - Object Pooling

Discussion in 'Scripting' started by BDR530, Jun 8, 2016.

  1. BDR530

    BDR530

    Joined:
    Feb 8, 2016
    Posts:
    12
    Hello , I'm trying to disable some game objects that are spawned with the object pooling. The game objects that I want to disable are enemies, they must be disable when is active another game object that I have chosen.

    I tried this but it does not work:

    Code (CSharp):
    1.  using UnityEngine;
    2. using System.Collections;
    3. public class ifBossActive : MonoBehaviour {
    4.      public GameObject boss;
    5.      private GameObject[] enemies;
    6.      void Start () {
    7.          enemies = GameObject.FindGameObjectsWithTag ("Enemy");
    8.      }
    9.        
    10.      void Update () {
    11.        
    12.          if (boss.activeInHierarchy) {
    13.              for(int i = 0; i < enemies.Length; i++)
    14.              {
    15.                  enemies [i].SetActive (false);
    16.              }
    17.          }
    18.      }
    19. }
    This is the code for the object pooling (used for enemies):

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. public class enemiesGen : MonoBehaviour {
    7.      public float spawnTime = 0.1f;
    8.      public GameObject enemy;
    9.      public int pooledAmount = 8;
    10.      List<GameObject> enemies;
    11.    
    12.   void Start () {
    13.          enemies = new List<GameObject> ();
    14.          for (int i = 0; i < pooledAmount; i++)
    15.          {
    16.              GameObject obj = (GameObject)Instantiate(enemy);
    17.              obj.SetActive (false);
    18.              enemies.Add(obj);
    19.          }
    20.          InvokeRepeating ("spawnEnemy", spawnTime, spawnTime);
    21.      }
    22.    
    23.   void spawnEnemy () {
    24.          for (int i = 0; i < enemies.Count; i++) {
    25.              if (!enemies [i].activeInHierarchy)
    26.              {
    27. transform.position = new Vector3 (transform.position.x, transform.position.y, transform.position.z + Random.Range(50f, 250f));
    28.  
    29.                  enemies [i].transform.position = transform.position;
    30.                  enemies [i].transform.rotation = transform.rotation;
    31.                  enemies [i].SetActive (true);
    32.  
    33.                  break;
    34.              }
    35.          }
    36.      }
    37. }
    How can I fix? Thanks in advance.
     
  2. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    First of all, C# prefers classes with pascal case (aka the first letter is uppercase too)
    The boss is child of something, that can get deactivated?
    Did you do debugs?
     
    BDR530 likes this.
  3. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    I am not sure where your problem is, the SetActive(false) works fine.

    I did a test to see if this all worked out fine. (and it did)

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using System.Collections.Generic;
    5.  
    6. public class test : MonoBehaviour {
    7.     public int maxSpawn = 8;
    8.     public float spawnTime = 0.1f;
    9.     public GameObject enemyToSpawn;
    10.     private List<GameObject> enemies;
    11.     private float nextSpawn = 0;
    12.  
    13.     void Start() {
    14.         // make sure that if you are not using a prefab, that we disable the current enemy
    15.         if (enemyToSpawn.activeInHierarchy)
    16.             enemyToSpawn.SetActive(false);
    17.  
    18.         // keep a list of enemies
    19.         enemies = new List<GameObject>();
    20.  
    21.         // this works perfectly
    22.         //for (var i = 0; i < maxSpawn; i++) {
    23.         //    var enemySpawned = Instantiate(enemyToSpawn);
    24.         //    enemies.Add(enemySpawned);
    25.         //    enemySpawned.SetActive(false);
    26.         //}
    27.        
    28.     }
    29.  
    30.  
    31.     void Update() {
    32.         // check all the enemies to see if they are still alive.
    33.         // if not, disable them
    34.         foreach (var enemy in enemies)
    35.         {
    36.             if (enemy.activeInHierarchy)
    37.             {
    38.                 var health = enemy.GetComponent<Health>();
    39.                 if (health != null)
    40.                 {
    41.                     if (health.health <= 0) enemy.SetActive(false);
    42.                 }
    43.             }
    44.         }
    45.         // instead of invoke repeating, lets use timed events
    46.         if (nextSpawn > Time.time) return;
    47.         SpawnEnemy();
    48.     }
    49.  
    50.     void SpawnEnemy() {
    51.         // keep count and make sure we dont go over our limit
    52.         var count = 0;
    53.         // this will keep the enemy we spawn
    54.         GameObject enemySpawned = null;
    55.         // go through each current enemy and see if it is active
    56.         foreach (var enemy in enemies) {
    57.             if (enemy.activeInHierarchy)
    58.                 count++;
    59.             else // if it is not active, keep the first one we find
    60.                 if(enemySpawned == null) enemySpawned = enemy;
    61.         }
    62.  
    63.         // if we can spawn
    64.         if (count < maxSpawn) {
    65.             // if we didnt find an enemy in the list, make one and add it to the list.
    66.             if (enemySpawned == null)
    67.             {
    68.                 enemySpawned = Instantiate(enemyToSpawn);
    69.                 enemies.Add(enemySpawned);
    70.             }
    71.  
    72.             // set the position, rotation and make it active.
    73.             enemySpawned.transform.position = transform.position;
    74.             enemySpawned.transform.rotation = transform.rotation;
    75.             enemySpawned.SetActive(true);
    76.  
    77.             // advance the time, but only if we spawned an enemy
    78.             nextSpawn = Time.time + spawnTime;
    79.         }
    80.     }
    81. }
    82.  
    83.  
    84. public class Health : MonoBehaviour {
    85.     public int health = 100;
    86.     public int maxHealth = 100;
    87.  
    88.     // methods used for broadcasting damage/healing
    89.     public void Damage(int amount) {
    90.         health -= amount;
    91.         if(health > maxHealth) health = maxHealth;
    92.         if(health < 0) health = 0;
    93.     }
    94.  
    95.     public void Heal(int amount){
    96.         health += amount;
    97.         if(health > maxHealth) health = maxHealth;
    98.         if(health < 0) health = 0;
    99.     }
    100. }
     
    BDR530 likes this.
  4. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    OK, I see your problem.

    Every 0.1 seconds, you activate all of your enemies, which means all 8 or so enemies activate at the same time. There is no "pooling"

    So, every frame, if the boss is there, all of the enemies deactivate, up to 0.1 seconds later, the all activate, and then the next frame they all deactivate again.
     
    BDR530 likes this.
  5. BDR530

    BDR530

    Joined:
    Feb 8, 2016
    Posts:
    12
    Thanks for the answers!

    I tried to change the object pooling directly, in this way:

    Code (CSharp):
    1.  
    2.  
    3. public GameObject boss;
    4.  
    5. void SpawnEnemy() {
    6.  
    7. for (int i = 0; i < enemies.Count; i++) {
    8. if (!enemies [i].activeInHierarchy && !boss.activeInHierarchy)
    9. {
    10. transform.position = new Vector3 (transform.position.x, transform.position.y, transform.position.z + Random.Range(50f, 250f));
    11. enemies [i].transform.position = transform.position;
    12. enemies [i].transform.rotation = transform.rotation;
    13. enemies [i].SetActive (true);
    14. break;
    15. }
    16.  
    17. if (boss.activeInHierarchy)
    18. {
    19. spawnTime = 0f;
    20. enemies [i].SetActive (false);
    21. CancelInvoke ();
    22. break;
    23. }
    24. }
    25. }
    But I still can not disable.
    PS: the boss is a prefab located in Prefabs/ folder and it is spawned after 50 seconds of the game.
     
  6. bigmisterb

    bigmisterb

    Joined:
    Nov 6, 2010
    Posts:
    4,221
    you should separate your concerns here.

    1, you want to disable the enemies when the boss is active, that needs to happen every frame, so it should be put into an update.

    2, in SpawnEnemy, if the boss is active, you need to just exit the method.
     
    BDR530 likes this.
  7. BDR530

    BDR530

    Joined:
    Feb 8, 2016
    Posts:
    12
    Thank you, now everything works perfectly. :)
     
  8. bomal

    bomal

    Joined:
    Jul 3, 2018
    Posts:
    6
    Hi,
    I know this post is very old, but I'm looking for a solution like this. how did you solve it Thank you very much