Search Unity

Question Check if all Gameobjects inside a list are Inactive

Discussion in 'Scripting' started by Only4gamers, Jun 9, 2021.

  1. Only4gamers

    Only4gamers

    Joined:
    Nov 8, 2019
    Posts:
    327
    Hello everyone,
    I am working on an Enemy Wave system. So it will check if there is no enemy is active in the scene. If there is no enemy, than it will spawn 1 enemy only.
    I tried different scripts from internet but it always spawning all 5 enemies one by one every second.

    Code (CSharp):
    1. IEnumerator CheckForAICars()
    2.     {
    3.         while(true)
    4.         {
    5.             yield return new WaitForSeconds(1f);
    6.             // Check If there is no active enemy than activate an enemy from Object pool
    7.             if(!ObjectPool.SharedInstance.IsEnemyCarActive("Car1(Clone)"))
    8.             {
    9.                 Transform waypoint = FindClosestWaypoint().transform;
    10.                 GameObject AICar = ObjectPool.SharedInstance.GetPooledObjectWithName("Car1(Clone)");
    11.                 AICar.transform.position =  waypoint.transform.position;
    12.                 // rocket.transform.rotation = Quaternion.identity;
    13.                 AICar.transform.rotation = waypoint.transform.rotation;
    14.                 AICar.SetActive(true);
    15.             }
    16.         }
    17.     }
    Code (CSharp):
    1. public bool IsEnemyCarActive(string name)
    2.   {
    3.     bool active = true;
    4.     List<GameObject> cars = new List<GameObject>();
    5.  
    6.     // There are some other objects inside object pool so only picking wanted objects and adding them to a temporary list
    7.     for (int i = 0; i < pooledObjects.Count; i++)
    8.     {
    9.       if (!pooledObjects[i].activeInHierarchy && pooledObjects[i].name == name)
    10.       {
    11.         cars.Add(pooledObjects[i]);
    12.       }
    13.     }
    14.  
    15.     foreach(GameObject car in cars)
    16.     {
    17.       if(car.activeSelf)
    18.       {
    19.         active = true;
    20.       }
    21.       else
    22.       {
    23.         active = false;
    24.        
    25.       }
    26.     }
    27.     return active;
    28.   }
    I tried different scripts from internet and tried different approaches but always same result.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,735
    To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?

    Knowing this information will help you reason about the behavior you are seeing.

    You can also put in Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    If you are running a mobile device you can also view the console output. Google for how on your particular mobile target.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    It isn't about "trying different scripts," but rather about using what you find as examples, understanding it, and adapting it to your needs.

    How to use scripts online and / or to do tutorials properly:

    Tutorials are a GREAT idea. Tutorials should be used this way:

    Random scripts are also great. But they have the same requirements:

    Step 1. Follow the tutorial and do every single step of the tutorial 100% precisely the way it is shown. Even the slightest deviation generally ends in disaster. That's how software engineering works. Every single letter must be spelled, capitalized, punctuated and spaced (or not spaced) properly. Fortunately this is the easiest part to get right. Be a robot. Don't make any mistakes. BE PERFECT IN EVERYTHING YOU DO HERE.

    Step 2. Go back and work through every part of the tutorial again, and this time explain it to your doggie. See how I am doing that in my avatar picture? If you have no dog, explain it to your house plant. If you are unable to explain any part of it, STOP. DO NOT PROCEED. Now go learn how that part works. Read the documentation on the functions involved. Go back to the tutorial and try to figure out WHY they did that. This is the part that takes a LOT of time when you are new. It might take days or weeks to work through a single 5-minute tutorial. Stick with it. You will learn.

    Step 2 is the part everybody seems to miss. Without Step 2 you are simply a code-typing monkey and outside of the specific tutorial you did, you will be completely lost.

    Of course, all this presupposes no errors in the tutorial. For certain tutorial makers (like Unity, Brackeys, Imphenzia, Sebastian Lague) this is usually the case. For some other less-well-known content creators, this is less true. Read the comments on the video: did anyone have issues like you did? If there's an error, you will NEVER be the first guy to find it.

    Beyond that, Step 3, 4, 5 and 6 become easy because you already understand!
     
    Only4gamers likes this.
  3. Only4gamers

    Only4gamers

    Joined:
    Nov 8, 2019
    Posts:
    327
    Thank you so much for another helpful reply. But I am not following any tutorial. As script is nothing too complicated I am understanding Script well and I created it myself. My question is "
    How to Check if all Gameobjects inside a list are Inactive
    ". And return true or false once, after checking all objects inside the list.
    So only important part of the script is this, and maybe that's where I am doing mistake.
    Code (CSharp):
    1. foreach(GameObject car in cars)
    2.     {
    3.       if(car.activeSelf)
    4.       {
    5.         active = true;
    6.       }
    7.       else
    8.       {
    9.         active = false;
    10.      
    11.       }
    12.     }
    13.     return active;
    Thanks
     
  4. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,486
    Your function above sets "active" for each car in your cars list which means it resets it for each car. In the end, all the code does above is set active to represent the last car.

    For starters, "active = car.activeSelf;" does the same thing without the if/else but is still the wrong logic.

    If you only want to check if all of the cars are inactive then as soon as you find one that is active the answer is "false" so you don't need to check them all so do:
    Code (CSharp):
    1. foreach(GameObject car in cars)
    2. {
    3.    if (car.activeSelf)
    4.       return false;
    5. }
    6.  
    7. return true;
    8.  
    I will add that your code is also very wasteful because it creates a list, adds stuff to it then simply returns a true/false. All that has to be cleared up. From what I see, look for your cars and if any single one is active then return false and you're done. You don't even need to look through them all or create a list just to throw it away.
     
    Only4gamers likes this.
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,486
    So is it not simply this?

    Code (CSharp):
    1. public bool IsEnemyCarActive(string name)
    2. {
    3.     foreach(var obj in pooledObjects)
    4.     {
    5.        if (!obj.activeInHierarchy &&
    6.            obj.name == name &&
    7.            obj.activeSelf)
    8.         {
    9.            return false;
    10.         }
    11.     }
    12.  
    13.     return true;
    14. }
     
    Only4gamers likes this.
  6. Only4gamers

    Only4gamers

    Joined:
    Nov 8, 2019
    Posts:
    327
    Thank you so much for reply but again same result. All 5 enemy cars are spawning one by one. While only one should spawn.
     
  7. Only4gamers

    Only4gamers

    Joined:
    Nov 8, 2019
    Posts:
    327
    While this script is working:
    Code (CSharp):
    1. bool allInActive = false;
    2.  
    3.     for (int i = 0; i < cars.Count; i++)
    4.     {
    5.      
    6.       if (cars[i].activeInHierarchy)
    7.       {
    8.           allInActive = false;
    9.           break;
    10.       }
    11.  
    12.       else if(!cars[i].activeInHierarchy && i == 4)
    13.       {
    14.         allInActive  = true;
    15.       }
    16.   }
    17.  
    18.       return allInActive;
    Maybe you can give me a better script with the help of above script.