首页 > 解决方案 > 为什么我的代码不会破坏列表的所有对象,而是随机保存其中一些?(统一 2d)

问题描述

首先感谢您抽出宝贵时间,对我的英语和低技能感到抱歉。基本上我在做这个无尽的跑步者,玩家向前移动并跳过东西。为了让它永无止境,我制作了一个脚本,该脚本在我附加到脚本的预制件之间随机选择一个预制件,并在之前生成的另一个平台的位置(使用空对象)的末尾生成它。要在你输掉游戏后重置游戏,我需要删除所有生成并保存在列表中的平台,但我的问题是脚本每隔一段时间就会跳过其中一个,导致它在重置并重新启动后仍然存在。这是我的代码:

 public void Reset()
    {
        deathMenu.gameObject.SetActive(false);
        for (int i = 0; i < generatore.getPooled().Count; i++)
        {
            if (generatore.getPooled()[i] == null)
            {
                i++;
            }

            else
            {
                generatore.getPooled()[i].gameObject.SetActive(false);
                if (!generatore.getPooled()[i].gameObject.activeInHierarchy)
                {
                    Destroy(generatore.getPooled()[i].gameObject);
                }
                if (i > 0)
                {
                    if (generatore.getPooled()[i - 1] == null && generatore.getPooled()[i + 1] == null)
                    {
                        Destroy(generatore.getPooled()[i].gameObject);
                    }
                }

            }
        }
        player.transform.position = playerStartPoint;
        generatore.SetEndPosition(endPosition);
        player.gameObject.SetActive(true);
        scoreManager.scoreCounter = 0;
        scoreManager.scoreIncrease = true;
    }

它基本上获取列表的平台(generatore.getPooled()),将它们设置为非活动状态,然后将它们一一删除。我必须在删除它们之前将它们设置为非活动状态,因为由于某些原因,如果我只删除它们,它会跳过更多平台,我什至尝试通过添加来删除脚本跳过的那些:

if (generatore.getPooled()[i - 1] == null && generatore.getPooled()[i + 1] == null)
                    {
                        Destroy(generatore.getPooled()[i].gameObject);
                    }

但它仍然跳过它们。 这就是我的意思

标签: c#unity3d

解决方案


  1. 首先,您为什么要在循环内的i++第一个案例中做客栈?if

    因为i++在每次迭代之后无论如何都会完成,所以它不会跳过当前项目,而是跳过下一个项目!您宁愿使用continue

  2. 然后你反复打电话

    generator.getPooled()
    

    它总是返回一个新列表(我猜)。这不仅在性能方面不好,而且在您从池中删除条目时(我想在您销毁它们时会发生某处)所有其他项目很可能会向上移动一步,从而改变它们的索引。因此,由于您不断增加索引i,因此可能会发生元素被移动到您已经通过的索引的情况,因此这再次导致跳过其中一些。

  3. 然后你打电话的条件Destroy是相当多余的。紧接着

    someGameObject.SetActive(false);
    

    检查

    if(!someGameObject.activeInHierarchy)
    

    将永远是正确的(除非在脚本中发生了一些黑暗魔法,OnDisable您将自己再次设置为活跃 - 这听起来很不可思议^^)

  4. 而且由于您无论如何都要销毁它(参见 3.),实际上根本不需要先将其设置为非活动状态。

  5. 而且由于您将始终销毁对象(请参见 3.),因此通过索引进行的下一次检查毫无意义,因为无论如何您已经销毁了该对象。

所以总而言之,你的代码会缩小到

foreach (var pooled in generatore.getPooled())
{
    if (!pooled) continue;
  
    Destroy(pooled.gameObject);
}
// TODO: clear the pool so there are no null elements remaining forever

推荐阅读