Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Removing dead enemies from an iterating list

Discussion in 'Scripting' started by DeathByRhino, Feb 14, 2016.

  1. DeathByRhino

    DeathByRhino

    Joined:
    Jul 30, 2015
    Posts:
    33
    So I have a series of enemies in a list, constantly in a coroutine and told when to attack by a foreach loop. When an enemy dies, he notifies the class containing the list to remove it. Since I can't remove it directly since the list is under an iteration, I tried instead to put the dead enemies in a Dead Enemy list and remove them from the main list after the foreachloop. However, how would I remove a series of GameObjects in a list(Dead Enemy) from another list (main list)? I tried a foreach loop that removes each dead enemy from the mainlist, but that ends up freezing the editor.
     
  2. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    Code (CSharp):
    1. for (int n = 0; n < enemy.Count) {
    2.    if (enemy[n].isDead) {
    3.       enemy.RemoveAt(n);
    4.       n--;
    5.    }
    6. }
     
    DeathByRhino likes this.
  3. DeathByRhino

    DeathByRhino

    Joined:
    Jul 30, 2015
    Posts:
    33
    Can you explain why n is decreasing, or why n starts at 0?
     
  4. DeathByRhino

    DeathByRhino

    Joined:
    Jul 30, 2015
    Posts:
    33
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4.  
    5. public class TurnManager : MonoBehaviour
    6. {
    7.     public GameObject currentarena;
    8.     public GameObject enemyAttacking;
    9.     public List<GameObject> enemylist = new List<GameObject>();
    10.     public List<GameObject> enemiesdefeated = new List<GameObject>();
    11.     GameObject[] currentenemies;
    12.     GameObject player;
    13.     public int direction;
    14.  
    15.     void Awake()
    16.     {
    17.  
    18.     }
    19.     public void SpawnDone()
    20.     {
    21.  
    22.     }
    23.  
    24.     public void StartCombat()
    25.     {
    26.         player = GameObject.FindGameObjectWithTag("Player");
    27.         EnemyCount();
    28.         //StartCoroutine(EnemyTurn());
    29.     }
    30.     void Update()
    31.     {
    32.  
    33.     }
    34.     void EnemyCount()
    35.     {
    36.         enemylist.Clear();
    37.         currentenemies = GameObject.FindGameObjectsWithTag("enemy");
    38.         Debug.Log("EnemyCount");
    39.         if (currentenemies.Length > 0)
    40.         {
    41.             foreach (GameObject character in currentenemies)
    42.             {
    43.                 enemylist.Add(character);
    44.                 enemylist.Sort(delegate (GameObject a, GameObject b)
    45.                 {
    46.                     return (a.GetComponent<EnemyVariables>().speed).CompareTo(b.GetComponent<EnemyVariables>().speed);
    47.                 });
    48.             }
    49.         }
    50.         else if(currentenemies.Length == 0)
    51.         {
    52.             EndCombat();
    53.             Debug.Log("End Combat");
    54.         }
    55.         StartCoroutine(EnemyTurn());
    56.     }
    57.     public void EnemyDeath(GameObject enemy, int dir)
    58.     {
    59.        //enemylist.Remove(enemy);
    60.        //enemiesdefeated.Add(enemy);
    61.         direction = dir;
    62.  
    63.     }
    64.     IEnumerator EnemyTurn()
    65.     {
    66.         foreach (GameObject enemy in enemylist)
    67.         {
    68.             enemyAttacking = enemy;
    69.             Debug.Log("EnemyTurn");
    70.             EnemyScript attackscript = enemy.GetComponent<EnemyScript>();
    71.             attackscript.TurnChosen();
    72.             while (attackscript.attacking)
    73.             {
    74.  
    75.                 yield return null;
    76.  
    77.             }
    78.         }
    79.         for (int n = enemylist.Count - 1; n >= 0; n--)
    80.         {
    81.             if (enemylist[n].tag == "dead")
    82.             {
    83.                 enemylist.RemoveAt(n);
    84.              
    85.             }
    86.         }
    87.         Debug.Log("EnemyTurn Finish");
    88.             EnemyCount();
    89.        
    90.             //StartCoroutine(EnemyTurn());
    91.         }
    92.  
    93.     public void EndCombat()
    94.     {
    95.         //player.SendMessage("EndCombat()");
    96.         player.GetComponent<PlayerCombatScript>().EndCombat();
    97.         enemylist.Clear();
    98.         currentarena.GetComponent<BattlegroundData>().ChangeArena(direction);
    99.         Debug.Log("EnemyManager Exit");
    100.     }
    101. }
    this is the code of the turn manager with the enemylist. the foreach and for loop combo seems to be responsible for freezing the editor
     
  5. LeftyRighty

    LeftyRighty

    Joined:
    Nov 2, 2012
    Posts:
    5,148
    why not just have the "enemy" remove itself from the list when it's set to dead rather than trying to do them all together in some "control" loop.


    also, in passing, lines 41-48, you are sorting every time you add something... wouldn't it be alot more efficient to add everything and sort the list at the end. Nothing in that code is dependent on the order.
     
  6. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    Removing elements from the list as you itterate backwards is a common way to remove items. That way your iteration doesn't get mixed up.

    The code sample is invalid, but it should read something like this.

    Code (CSharp):
    1. for (int n = enemy.Count - 1; n >= 0; n--) {
    2.    if (enemy[n].isDead) {
    3.       enemy.RemoveAt(n);
    4.    }
    5. }
     
    Ksanone, Griffo and aer0ace like this.
  7. gorbit99

    gorbit99

    Joined:
    Jul 14, 2015
    Posts:
    1,350
    @BoredMormon I also saw a bunch of people just simply iterate from 0 and just removing 1,when they remove something from the list. I used this technique quite a lot. My code sample was invalid, yes, I forgot the n++ from the end.

    @DeathByRhino You should learn a bit of c# before jumping into unity, because I think you don't understand the basic loops