Search Unity

Alternative to unityeditor.ArrayList.Remove() for array variable type?

Discussion in 'Scripting' started by ayuuDubbed, May 1, 2021.

  1. ayuuDubbed

    ayuuDubbed

    Joined:
    Aug 8, 2020
    Posts:
    4
    Hello!
    I was making a script to remove the objects in my array once they were destroyed, I stumbled across ArrayList.Remove() and it was perfect, until I realized that it only works inside the unity editor, so I tried making a workaround and eventually got to this


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEditor;
    5. using UnityEngine.SceneManagement;
    6. public class GameManager : MonoBehaviour
    7. {
    8.     public GameObject[] enemies;
    9.     private float nullCount = 0;
    10.     // Start is called before the first frame update
    11.     void Start()
    12.     {
    13.        
    14.     }
    15.  
    16.     // Update is called once per frame
    17.     void Update()
    18.     {
    19.         foreach(GameObject currentEnemy in enemies)
    20.         {
    21.             if (currentEnemy)
    22.             {
    23.                 Debug.Log("Enemy Still Alive!");
    24.                 nullCount -= 1;
    25.                 nullCheck();
    26.             }
    27.             else if (!currentEnemy)
    28.             {
    29.                 Debug.Log("Enemy Dead");
    30.                 nullCount += 1;
    31.                 enemies[System.Array.IndexOf(enemies, currentEnemy)] = null;
    32.                 nullCheck();
    33.             }
    34.         }
    35.        
    36.     }
    37.  
    38.     void nullCheck()
    39.     {
    40.         if (nullCount == 0)
    41.         {
    42.             SceneManager.LoadScene("Scene 3");
    43.         }
    44.     }
    45. }
    46.  
    The problem with this system is that if my player is say a speed runner and he brutally murders every enemy within 0.69 seconds this will cause the game to take forever to move on to the next scene.

    I want to know a faster way of doing this, or even better, an alternative to ArrayList.Remove.

    (Also sorry for no comments, I only use them on huge scripts.)
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,727
    Arrays are immutable in size, so it seems a List<T> would be more appropriate here.

    Code (csharp):
    1. public List<GameObject> enemies;
    With lists you just remove the item.

    Code (csharp):
    1. enemies.Remove( doomedEnemy);
    In fact, if you want to remove all nulls or Destroyed objects (remember, destroyed things don't become destroyed until end of current frame), then all you need is:

    Code (csharp):
    1. enemies.RemoveAll( x => !x);
    Means, "for all x that are not true, remove them," sort of a hinky-janky usage of a lambda and Unity's null boolean override thingy, but it works for anything derived from UnityEngine.Object.
     
    Lekret likes this.
  3. Lekret

    Lekret

    Joined:
    Sep 10, 2020
    Posts:
    358
    If your code needs to be efficient, then you can create very simple event model. Without modifying arrays/lists and iterating through all of that in Update.
    Code (CSharp):
    1.  
    2. public class Enemy : MonoBehaviour
    3. {
    4.     public event UnityAction Died;
    5.  
    6.     public void ApplyDamage()
    7.     {
    8.         Died?.Invoke();
    9.     }
    10. }
    11.  
    12. public class GameManager : MonoBehaviour
    13. {
    14.     public Enemy[] enemies;
    15.  
    16.     private float enemyCount;
    17.  
    18.     private void Awake()
    19.     {
    20.         enemyCount = enemies.Length;
    21.     }
    22.  
    23.     private void OnEnable()
    24.     {
    25.         foreach(var enemy in enemies)
    26.             enemy.Died += OnEnemyDied;
    27.     }
    28.  
    29.     private void OnDisable()
    30.     {
    31.         foreach(var enemy in enemies)
    32.             if (enemy != null)
    33.                 enemy.Died -= OnEnemyDied;
    34.     }
    35.  
    36.     private void OnEnemyDied()
    37.     {
    38.         enemyCount--;
    39.         if (enemyCount == 0)
    40.             SceneManager.LoadScene("Scene 3");
    41.     }
    42. }
     
    Last edited: May 1, 2021