Unity 2D中如何检测GameObject列表内的对象是否已被销毁
Unity 战斗屏障存活敌人检测逻辑补全
需求背景
- 维护
GameObject类型的敌人列表,实现所有敌人被消灭前战斗屏障保持锁定的效果,敌人列表设置为public类型方便后续复用这套逻辑 - 现有触发逻辑:玩家碰撞到屏障触发区域时,遍历敌人列表统计存活敌人数量:
- 仍有敌人存活:启用战斗屏障碰撞体、切换为屏障显示精灵
- 敌人全部被消灭:禁用屏障碰撞体、切换为无屏障的消失精灵
- 待补全逻辑:for循环内的判断条件,需要检测列表中对应敌人GameObject是否已被销毁(引用失效、对象不存在/Inspector面板显示为None)
原有待补全代码
public GameObject fightBarrier; public List<GameObject> enemies = new List<GameObject>(); public SpriteRenderer Barrier_0; public SpriteRenderer Barrier_1; public SpriteRenderer Barrier_2; public SpriteRenderer Barrier_3; public Sprite Barrier; public Sprite noBarrier; private int enemiesAmountCheck; // overrided because it's inheriting from another script protected override void OnCollide(Collider2D coll) { if (coll.name == "Player") { enemiesAmountCheck = enemies.Count; for (int i = 0; i < enemies.Count - 1; i++) { // This if statement has to check if the GameObject doesn't exist (AKA the GameObject is None) if (enemies[i]... ) { enemiesAmountCheck = enemiesAmountCheck - 1; } } if (enemiesAmountCheck > 0) { fightBarrier.GetComponent<BoxCollider2D>().enabled = true; Barrier_0.sprite = Barrier; Barrier_1.sprite = Barrier; Barrier_2.sprite = Barrier; Barrier_3.sprite = Barrier; } else { fightBarrier.GetComponent<BoxCollider2D>().enabled = false; Barrier_0.sprite = noBarrier; Barrier_1.sprite = noBarrier; Barrier_2.sprite = noBarrier; Barrier_3.sprite = noBarrier; } } }
补全方案
核心判断条件
Unity对UnityEngine.Object(GameObject的直接基类)重载了==运算符,直接判断enemies[i] == null即可同时覆盖两种失效场景:
- 列表元素本身未在Inspector面板赋值,对应字段显示为None
- 敌人GameObject已经被
Destroy()方法销毁,引擎原生层对象已释放
补全后的if判断为:
if (enemies[i] == null) { enemiesAmountCheck--; }
原有代码bug修复
原for循环的边界条件写为i < enemies.Count - 1,会漏掉列表最后一个敌人的检测,需要修改为i < enemies.Count才能遍历所有列表元素,否则会出现敌人全灭但屏障仍锁定的异常。
补全后完整逻辑代码
public GameObject fightBarrier; public List<GameObject> enemies = new List<GameObject>(); public SpriteRenderer Barrier_0; public SpriteRenderer Barrier_1; public SpriteRenderer Barrier_2; public SpriteRenderer Barrier_3; public Sprite Barrier; public Sprite noBarrier; private int enemiesAmountCheck; // overrided because it's inheriting from another script protected override void OnCollide(Collider2D coll) { if (coll.name == "Player") { enemiesAmountCheck = enemies.Count; // 修复循环边界,遍历所有敌人条目 for (int i = 0; i < enemies.Count; i++) { // 检测敌人对象是否未赋值/已被销毁 if (enemies[i] == null) { enemiesAmountCheck--; } } if (enemiesAmountCheck > 0) { fightBarrier.GetComponent<BoxCollider2D>().enabled = true; Barrier_0.sprite = Barrier; Barrier_1.sprite = Barrier; Barrier_2.sprite = Barrier; Barrier_3.sprite = Barrier; } else { fightBarrier.GetComponent<BoxCollider2D>().enabled = false; Barrier_0.sprite = noBarrier; Barrier_1.sprite = noBarrier; Barrier_2.sprite = noBarrier; Barrier_3.sprite = noBarrier; // 可选优化:清空列表内的空引用,避免后续重复遍历无效元素 enemies.RemoveAll(enemy => enemy == null); } } }
优化说明:检测到所有敌人被消灭后,可以调用
enemies.RemoveAll(enemy => enemy == null)清理列表里的空引用,避免后续触发检测时重复遍历已销毁的无效元素,减少不必要的性能消耗。
内容的提问来源于stack exchange,提问作者Anthony Ruiz
相关产品推荐
相关产品推荐

