简体   繁体   English

检查数组的所有对象是否同时处于活动状态 Unity C#

[英]Checking if all objects of an array is active at the same time Unity C#

I've tried to make a script that if all the lights in my scene tagged "Light" are active at the same time, the game proceeds.我尝试编写一个脚本,如果场景中标记为“Light”的所有灯光同时处于活动状态,则游戏会继续进行。 None of the answers I've found have helped so far.到目前为止,我找到的答案都没有帮助。 I always end up with it only scanning the active objects, just randomly jumping out of the loop, or stopping when it has found one object that's active.我总是最终只扫描活动对象,只是随机跳出循环,或者在找到一个活动的 object 时停止。 Here is a simple piece of code that should have worked according to other posts这是一段简单的代码,根据其他帖子应该可以工作

    void Update()
    {
        bool allActive = false;
        GameObject[] allLights = GameObject.FindGameObjectsWithTag("Light");
        if(currenObjective > 0 && currenObjective < 3)
        {
            for (int i = 0; i < allLights.Length; i++)
            {
                if (allLights[i].activeInHierarchy)
                {
                    allActive = true;
                    break;
                }
            }
            if (allActive)
            {
                currentObjective = 2;
            }
        }
    }

This code just sets the allActive variable to true at the moment one light is turned on.此代码只是在打开盏灯时将 allActive 变量设置为 true。

You would need to invert the check:您需要反转检查:

private void Update()
{
    // Since Find is always a bit expensive I would do the cheapest check first
    if(currenObjective > 0 && currenObjective < 3)
    {
        var allLights = GameObject.FindGameObjectsWithTag("Light");
        var allActive = true;
        for (int i = 0; i < allLights.Length; i++)
        {
            if (!allLights[i].activeInHierarchy)
            {
                allActive = false;
                break;
            }
        }
        if (allActive)
        {
            currentObjective = 2;
        }
    }
}

Or You can do this in one line using Linq All或者您可以使用Linq All在一行中执行此操作

using System.Linq;

...

private void Update()
{
    // Since Find is always a bit expensive I would do the cheapest check first
    if(currenObjective > 0 && currenObjective < 3)
    {
        var allLights = GameObject.FindGameObjectsWithTag("Light");

        if (allLights.All(light => light.activeInHierarchy))
        {
            currentObjective = 2;
        }
    }
}

As a general note: You should avoid using FindGameObjectsWithTag every frame!作为一般说明:您应该避免每帧都使用FindGameObjectsWithTag Either store these references ONCE at start, or if you spawn more lights on runtime implement it event driven and add the newly spawned lights to a list and then use that list to check.要么在开始时将这些引用存储一次,要么在运行时生成更多灯光,实现它的事件驱动并将新生成的灯光添加到列表中,然后使用该列表进行检查。

If i understant you want to know if all objects are active: using Linq does the job如果我知道您想知道所有对象是否都处于活动状态:使用 Linq 就可以了

you have to add using system.Linq to your script.您必须使用 system.Linq 添加到您的脚本中。

    GameObject[] allLights = GameObject.FindGameObjectsWithTag("Light");
    bool result = allLights.All(p => p.activeInHierarchy);

you could simplify your code like this:你可以像这样简化你的代码:

private void Update()
{
    if(currenObjective > 0 && currenObjective < 3 && GameObject.FindGameObjectsWithTag("Light").All(p => p.activeInHierarchy))
    {
        currentObjective = 2;
    }
}

As says derHugo, FindGameObjectsWithTag is very expensive in each frame...正如 derHugo 所说,FindGameObjectsWithTag 在每一帧中都非常昂贵......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM