【问题标题】:Null GameObjects in foreach loopforeach 循环中的空游戏对象
【发布时间】:2017-03-18 19:21:27
【问题描述】:

我正在尝试遍历游戏对象列表并找到第一个在层次结构中不活动的游戏对象并返回该游戏对象。

我遇到的问题是我的 foreach 语句在“敌人”上不断返回 null

下面这个语句中的“敌人”是问题所在

“pizzaEnemyList 中的 GameObject 敌人”

列表中确实有一个游戏对象。如下图所示

private List<GameObject> pizzaEnemyList = new List<GameObject> ();

private GameObject FetchPizzaEnemy()
{
    GameObject pizzaEnemy = null;
    int count = 0;

    foreach (GameObject enemy in pizzaEnemyList)
    {
        if (enemy.activeInHierarchy == false)
        {
            pizzaEnemy = pizzaEnemyList [count];

            pizzaEnemyList.Remove (enemy);


            return pizzaEnemy;
        }
        count += 1;
    }

    return pizzaEnemy;
}

//我用来将敌人添加到列表中的函数。

public void DeactivateAndStoreEnemy(GameObject enemy)
{
    //decativates the enemy
    enemy.SetActive(false);



    //Store the enemy into the correct list
    if (enemy.name == "PizzaGuy")
    {
        pizzaEnemyList.Add (enemy);
    }
    else if (enemy.name == "FiresGuy")
    {
        friesEnemyList.Add (enemy);
    }
    else if (enemy.name == "SodaGuy")
    {
        sodaEnemyList.Add (enemy);
    }
}


public int PizzaListUnactiveEnemyCount()
{
    int unactiveEnemiesCount  = 0;

    foreach (GameObject enemies in pizzaEnemyList)
    {
        if (enemies.activeInHierarchy == false)
        {
            unactiveEnemiesCount += 1;
        }
    }

    return unactiveEnemiesCount;
}

【问题讨论】:

  • 你确定activeInHierarchy 确实是那个项目的假? (你确定它只是被禁用,而不是被销毁?)另外,你可以使用pizzaEnemy = enemy而不是pizzaEnemy = pizzaEnemyList [count],所以你不需要保留计数器变量。
  • 您的问题有点不清楚:FetchPizzaEnemy() 是否返回null?还是FetchPizzaEnemy() 在尝试访问enemy 上的activeInHierarchy 属性时抛出了NullReferenceException?
  • 你能证明你是在向pizzaEnemyList 添加项目吗?因为现在它是private,所以这意味着你没有从检查员统一添加它们。
  • @BrianSnow 当我将鼠标放在“foreach(pizzaEnemyList 中的 GameObject 敌人)”行中的“enemy”上时,它显示“null”

标签: c# unity3d foreach nullreferenceexception gameobject


【解决方案1】:

我已经测试了您的代码并且可以告诉您它可以工作如果游戏对象被正​​确添加并且它们实际上是不活动的。

您的问题很可能是没有将游戏对象正确添加到列表中,也可能没有确保 pizzaEnemyList 至少有 1 个项目设置为非活动状态。当您的列表中的所有项目都处于活动状态时,它返回 null 是正常的,因为它永远不会进入 if (enemy.activeInHierarchy == false)

如果你有一个 public List&lt;GameObject&gt; pizzaEnemyList; 并在统一检查器中设置会更好。除非此解决方案不适合您正在构建的游戏。

正如 Serlite 所说,您在使用 foreach 时不需要保留计数器,您的代码可能如下所示:

private GameObject FetchPizzaEnemy()
{
    GameObject pizzaEnemy = null;

    foreach (GameObject enemy in pizzaEnemyList)
    {
        if (enemy.activeInHierarchy == false)
        {
            pizzaEnemy = enemy;

            pizzaEnemyList.Remove(enemy);

            return pizzaEnemy;
        }
    }

    return pizzaEnemy;
}

编辑后编辑:

我已经用这个测试了你的代码,它可以工作:

private List<GameObject> pizzaEnemyList = new List<GameObject>();


void Start()
{
    GameObject pizzaGuy = GameObject.Find("PizzaGuy");    

    DeactivateAndStoreEnemy(pizzaGuy);
    Debug.Log(FetchPizzaEnemy());
}

private GameObject FetchPizzaEnemy()
{
    GameObject pizzaEnemy = null;

    foreach (GameObject enemy in pizzaEnemyList)
    {
        if (enemy.activeInHierarchy == false)
        {
            pizzaEnemy = enemy;

            pizzaEnemyList.Remove(enemy);

            return pizzaEnemy;
        }
    }

    return pizzaEnemy;
}

public void DeactivateAndStoreEnemy(GameObject enemy)
{
    enemy.name = "PizzaGuy";

    //decativates the enemy
    enemy.SetActive(false);



    //Store the enemy into the correct list
    if (enemy.name == "PizzaGuy")
    {
        pizzaEnemyList.Add(enemy);
    }
}

我的场景中有一个名为 PizzaGuy 的游戏对象。

【讨论】:

  • 感谢您的回复。我添加了我用来检查列表是否获取非活动对象的两个函数以及我用来将它们加载到游戏对象列表中的函数。
  • 敌人是我制作的玩家预制件。我使用 void Start () { PizzaGuy = GameObject.Find ("PizzaGuy");} 来查找预制件
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-21
  • 2013-05-20
  • 1970-01-01
  • 1970-01-01
  • 2014-03-06
相关资源
最近更新 更多