检查我的数组中的游戏对象数量

时间:2016-02-25 15:00:36

标签: c# unity3d

我需要知道剩下的enemyCans的数量,所以当没有剩余时,我可以触发我的胜利条件。现在,我的爆炸组件上有一个脚本,它可以正常运行,这意味着它可以移除任何爆炸范围内的敌人加农炮。
声明enemyCans并在start()方法中为其分配以下值:

GameObject[] enemyCans; //Before start
void Start() {
enemyCans = GameObject.FindGameObjectsWithTag("EnemyCannon");
}

然后,我在名为CannonKiller()的方法中使用该值,该方法遍历Enemy Cannon的变换以检查爆炸是否接近它们。我确信这不是最优雅的方式,但上面列出的方法如下:

 void CannonKiller()
{
    foreach(var cannon in GameObject.FindGameObjectsWithTag("EnemyCannon").Select(enemyCans => enemyCans.transform).ToArray())
    {
        foreach (var aCan in enemyCans)
        {
            float enemyDis = Vector3.Distance(cannon.position, transform.position);
            if (enemyDis <= 4)
            {
                Destroy(aCan);
            }
        }
    }
}

我希望能够检查并查看嵌套的foreach循环,看看敌人的数量是否为零所以我可以调用我的终结方法。我认为这样的事情会起作用:

if (enemyCans == 0) //placed inside the foreach
{
 finish("enemy");
}

但我错了。我如何检查他们是否没有剩下的敌人大炮,以便调用我的完成方法。

2 个答案:

答案 0 :(得分:1)

嗯,这段代码可行:

void CannonKiller()
    {
        foreach(var cannon in GameObject.FindGameObjectsWithTag("EnemyCannon").Select(enemyCans => enemyCans.transform).ToArray())
        {
            foreach (var aCan in enemyCans)
            {
                float enemyDis = Vector3.Distance(cannon.position, transform.position);
                if (enemyDis <= 4)
                {
                    Destroy(aCan);

                    bool allDestoyed = true;
                    foreach (GameObject o in enemyCans) 
                    {
                        if (o != null && o != aCan) 
                        {
                            allDestoyed = false;
                            break;
                        }
                    }

                    if (allDestoyed) 
                    {
                        // Here you know all are destroyed
                    }
                }
            }
        }
    }

但我必须说这是一种非常丑陋的编程方式;)

答案 1 :(得分:1)

如果可能的话,我建议避免使用那么多嵌套foreach循环 - 虽然Jerry的答案确实有效,但在最坏的情况下你基本上会有一个O(n 3 )复杂度算法,它有点难以阅读。

如果你的所有炮塔上都有碰撞器,那么你应该利用物理引擎。如果你使用像Physics.OverlapSphere这样的方法识别爆炸所袭击的炮塔,你的代码的意图至少会更加清晰。

因此调整CannonKiller()以摧毁命中炮塔并确定它们是否全部被摧毁(但以可以说是更整洁的方式),您的方法可能如下所示:

void CannonKiller()
{
    // Grab colliders in vicinity of explosion
    Collider[] hitColliders = Physics.OverlapSphere(transform.position, 4);
    foreach (Collider hitCollider in hitColliders){

        // Only act if collider belongs to an enemy cannon
        if (hitCollider.gameObject.tag == "EnemyCannon"){
            Destroy(hitCollider.gameObject);

            // If there are no non-null references to cannon objects, they're all destroyed
            if (enemyCans.FirstOrDefault(cannon => cannon != null) == null){

                // Execute finishing code, then probably break

            }
        }
    }
}

因为我看到你已经熟悉了LINQ,所以我将它用于&#34;所有被破坏的&#34;检查。

这可能不是最好的方法,但我认为它不会在不严重改变您的实施的情况下获得。 (像Joe建议的那样拥有一个管理器类是一种在类之间分配职责,并使代码更易于测试/维护的好方法 - 因此请务必深入研究,因为随着项目的增长,它会扩展得更好。)