Проверка одновременной активности всех объектов массива Unity C# - PullRequest
0 голосов
/ 08 мая 2020

Я попытался создать сценарий, который, если все источники света в моей сцене с тегом «Light» активны одновременно, игра продолжается. Ни один из найденных мной ответов пока не помог. Я всегда заканчиваю тем, что он сканирует только активные объекты, просто случайным образом выпрыгивая из l oop или останавливаясь, когда находит один активный объект. Вот простой фрагмент кода, который должен был работать согласно другим сообщениям.

    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;
            }
        }
    }

Этот код просто устанавливает для переменной allActive значение true в момент горит один свет.

Ответы [ 2 ]

3 голосов
/ 08 мая 2020

Если я понимаю, вы хотите знать, все ли объекты активны: использование Linq делает работу

, вы должны добавить using system.Linq в свой скрипт.

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

вы могли бы упростите свой код следующим образом:

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

Как говорит derHu go, FindGameObjectsWithTag очень дорого обходится в каждом кадре ...

3 голосов
/ 08 мая 2020

Вам нужно будет инвертировать чек:

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;
        }
    }
}

Или вы можете сделать это в одной строке, используя 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;
        }
    }
}

Общее примечание: вам следует избегать использования FindGameObjectsWithTag в каждом кадре! Либо сохраните эти ссылки ONCE при запуске, либо, если вы создадите больше источников света во время выполнения, реализуйте его на основе событий и добавьте вновь созданные источники света в список, а затем используйте этот список для проверки.

...