Checking through an array of objects

I have an array of WeightedButton (one of my scripts), and need to be able to check if 1 or more of them have a boolean value of true.

I have only used arrays once or twice over the past year as I mostly focus on artwork, and very basic scripting.
Does anyone know a quick and efficient way of checking through all the objects and check if a boolean value is true for at least 1?

Something like

public WeightedButton[] buttons;

bool CheckButtons()
{
    foreach(WeightedButton wb in buttons)
    {
        if (wb.boolean)
            return true;
    }
    return false;
}

This will return true as soon as it finds one button that has the boolean value set to true.

You could use a Linq query for it, assuming Unity supports Linq on arrays.

if(WeightedButtonArray.Any(wb => wb.boolean))
{
    //whatever you want to do here
}

For clarity you could say ‘wb.boolean == true’ but it is not necessary.

1 Like

For loops should normally do the trick. But a faster one liner is even better:
Array.Exists(array, b => { if (b) return true; else return false;This method returns true when the boolean array contains true

I am receiving no errors for this, but the state I have doesn’t seem to be setting itself.
What should happen is if one of the buttons isEnabld bool is true, the barrier is deactivated (renderer and collider), but the state machine set up to do this doesn’t seem to be setting itself.

Barrier.cs

using UnityEngine;
using System.Collections;

public class Barrier : MonoBehaviour
{

    public enum State
    {
        Active,
        Inactive,
    }

    public State state;
    public WeightedButton[] buttons;

    void Update()
    {
        if (state == State.Active)
        {
            MeshRenderer meshObject = GetComponent<MeshRenderer>();
            meshObject.enabled = true;
            BoxCollider meshCollider = GetComponent<BoxCollider>();
            meshCollider.enabled = true;
        }
        else
        {
            MeshRenderer meshObject = GetComponent<MeshRenderer>();
            meshObject.enabled = false;
            BoxCollider meshCollider = GetComponent<BoxCollider>();
            meshCollider.enabled = false;
        }
    }

    public void ForcedUpdate()
    {
        foreach (WeightedButton wb in buttons)
        {
            if (wb.isEnabled)
            {
                state = State.Inactive;
            }
        }
        state = State.Active;
    }
}

WeightedButton.cs

using UnityEngine;
using System.Collections;

public class WeightedButton : MonoBehaviour
{
    public bool isEnabled;
    public GameObject buttonObject;
    public Vector3 buttonOrigin = new Vector3(0f, 0.1f, 0f);
    public Vector3 buttonTarget = new Vector3(0f, 0.05f, 0f);
    public float moveSpeed;

    void OnCollisionEnter(Collision other)
    {
        StartCoroutine(MoveDown(buttonTarget));

        if (other.gameObject.tag == "Box" || other.gameObject.tag == "Player")
        {
            isEnabled = true;
        }
    }

    void OnCollisionExit(Collision other)
    {
        StartCoroutine(MoveUp(buttonOrigin));

        if (other.gameObject.tag == "Box" || other.gameObject.tag == "Player")
        {
            isEnabled = false;
        }
    }

    IEnumerator MoveDown(Vector3 target)
    {
        while (buttonObject.transform.localPosition != target)
        {
            buttonObject.transform.localPosition = Vector3.MoveTowards(buttonObject.transform.localPosition, target, moveSpeed * Time.deltaTime);
            yield return 0;
        }
    }

    IEnumerator MoveUp(Vector3 origin)
    {
        while (buttonObject.transform.localPosition != origin)
        {
            buttonObject.transform.localPosition = Vector3.MoveTowards(buttonObject.transform.localPosition, origin, moveSpeed * Time.deltaTime);
            yield return 0;
        }
    }
}

For @Timelog 's script make sure you add:using System.Linq;

1 Like

So used to Resharper I completely forgot to add that, thanks :smile:

You never know where people want to deploy to, which features do work and which not, i heard some platforms struggle a bit with Linq, such as iOs.
Also, the good old approach is (still) faster (not significantly for small and medium sized array though, so let’s ignore that), just not as much sugar syntax. Save everything you can, especially in games and if it runs often. :smile:
Anyway, i think it’s easier for him to understand as he’s an artist. :slight_smile:

Where do you call ForcedUpdate?
Also, you set the state to Inactive just to reset it to active immediately after the loop. That doesn’t seem to make any sense.

I noticed the setting mistake very quickly after putting it in there, so that is no longer there.
As I don’t really need to call a function, I have changed the function name to FixedUpdate so Unity can call it itself.

After adding a bit to FixedUpdate though, I am lo longer able to put a box on the button and have the barrier turn off.
I was trying to get it to set the barrier back to active when no boxes are on the connected buttons, but it didn’t work too well.

Barrier.cs

using UnityEngine;
using System.Collections;

public class Barrier : MonoBehaviour
{

    public enum State
    {
        Active,
        Inactive,
    }

    public State state;
    public WeightedButton[] buttons;

    void Update()
    {
        if (state == State.Active)
        {
            MeshRenderer meshObject = GetComponent<MeshRenderer>();
            meshObject.enabled = true;
            BoxCollider meshCollider = GetComponent<BoxCollider>();
            meshCollider.enabled = true;
        }
        else
        {
            MeshRenderer meshObject = GetComponent<MeshRenderer>();
            meshObject.enabled = false;
            BoxCollider meshCollider = GetComponent<BoxCollider>();
            meshCollider.enabled = false;
        }
    }

    public void FixedUpdate()
    {
        foreach (WeightedButton wb in buttons)
        {
            if (wb.isEnabled)
            {
                state = State.Inactive;
            }
            else
            {
                state = State.Active;
            }
        }
    }
}

WeightedButton.cs

using UnityEngine;
using System.Collections;

public class WeightedButton : MonoBehaviour
{
    public bool isEnabled;
    public GameObject buttonObject;
    public Vector3 buttonOrigin = new Vector3(0f, 0.1f, 0f);
    public Vector3 buttonTarget = new Vector3(0f, 0.05f, 0f);
    public float moveSpeed;

    void OnCollisionEnter(Collision other)
    {
        StartCoroutine(MoveDown(buttonTarget));

        if (other.gameObject.tag == "Box" || other.gameObject.tag == "Player")
        {
            isEnabled = true;
        }
    }

    void OnCollisionExit(Collision other)
    {
        StartCoroutine(MoveUp(buttonOrigin));

        if (other.gameObject.tag == "Box" || other.gameObject.tag == "Player")
        {
            isEnabled = false;
        }
    }

    IEnumerator MoveDown(Vector3 target)
    {
        while (buttonObject.transform.localPosition != target)
        {
            buttonObject.transform.localPosition = Vector3.MoveTowards(buttonObject.transform.localPosition, target, moveSpeed * Time.deltaTime);
            yield return 0;
        }
    }

    IEnumerator MoveUp(Vector3 origin)
    {
        while (buttonObject.transform.localPosition != origin)
        {
            buttonObject.transform.localPosition = Vector3.MoveTowards(buttonObject.transform.localPosition, origin, moveSpeed * Time.deltaTime);
            yield return 0;
        }
    }
}

You’re still doing something wrong. Now the state’s gonna toggle depending on the isEnabled value of each button.

One question that comes to my mind is, why don’t you handle everything in the OnCollisionXXX methods? You could set up a reference to the gameObject that you want to disable/manipulate and simply run the code there.
Then there’s no need to check it every update or fixed update, you can just rely on the Collision methods in this case.

It is in a separate script as I am going to have more than just buttons activating the barriers, it is simpler to have multiple scripts doing this, at least for me anyway.

But that still doesn’t fix my problem.

I am still unsure of how to do this.

All I need to do is set “state = State…” to Inactive is one or more of the buttons has the isEnabled bool true, and to set the state to Active if none of them are true.

I have continued to scour Google for this, but without knowing the syntactical term for it, I don’t really know what to specifically search for.