Controlling Object Active States With Booleans

First, a little background on my setup.
I have a Gate script which references an array of lights and an array of switches.
I have a Switch script which contains a public boolean array, meant to represent the lights.

What I need to do is, when the switches boolean state (state) is true, to change the state (on to off, or off to on) of the lights (SetActive).

If this isn’t very clear, I have put the scripts below.

Gate.cs

using UnityEngine;
using System.Collections;

public class Gate : MonoBehaviour {

    public GameObject[] lights;
    public Switch[] switches;
    private int lightCount;
   
    void Start()
    {
        foreach (GameObject l in lights)
        {
            l.SetActive(false);
        }
    }

    void Update ()
    {
        foreach(Switch s in switches)
        {
            if(s.state == true)
            {
               
            }
        }
    }
}

Switch.cs

using UnityEngine;
using System.Collections;

public class Switch : MonoBehaviour {

    public bool canBeUsed;
    public bool state;

    public bool[] lights;
   
    void Update ()
    {
        if (canBeUsed == true)
        {
            if (state == true)
            {
                state = false;
            }
            if (state == false)
            {
                state = true;
            }
        }
    }

    public void Clicked()
    {
        if (state == true)
        {
            state = false;
        }
        else
        {
            state = true;

            foreach(bool l in lights)
            {

            }
        }
    }
}

I’m not 100% sure of the question you’re asking, because there are several steps involved:

  1. detecting that the switch is clicked (collision box? coordinate check? make it a UIbutton?)
  2. getting that even to the correct light (is there a 1-to-1 mapping in the arrays? does it go by name? does a switch have an associated name it goes to, or just the array of its controlled lights?)
  3. actually toggling the light (you can do this by enabling/disabling the actual Unity light component, or if the light is really an unlit texture, then enabling/disabling the renderer, or replacing the “off” light with an “on” light when the state changes)

I hope this gives some tools to think about your problem a bit more and perhaps make some headway.

  1. I am currently calling the Clicked function with a UI button.
  2. The arrays area 1-1 mapping of each other, boolean [0] controls light [0] and so on.
  3. Getting the object to turn off is just a placeholder so I can get it all working before I add some fancy shader stuff.

What I am trying to do is build a switch puzzle, so depending on which lights the switch is set up to toggle (the boolean array), those lights are toggled when the switch is toggled.

This is the bit I am struggling with, mapping the arrays with 1-1 match, and getting them to operate correctly.

You want to use for loops rather than foreach loops. Since the arrays match 1 to 1, you need the same index to access each one. That’s a piece of data you just don’t have in a foreach.

for (int index = 0; index < someArray.Length; index++) {
lights[index].enabled = lightBools[index];
}

That said, since the Light component already has a bool attached to it (e.g. .enabled), why not alter those directly, and skip the parallel boolean array entirely?

And, you should definitely learn the ! operator. It means “not”:

lights[someIndex].enabled = !lights[someIndex].enabled;

Will toggle the light at position someIndex.

How would this even be implemented in my scripts?
I can very roughly see (just about) what this is meant to do, but I have no idea how this would work for my example.

One of two approaches. In both, Switch.js is placed somewhere where it can receive a message when the user presses it - looks like that’s what Click() does.

Switch has a reference to either:

A) A Gate, and an index of the light it manipulates (to be set in the inspector):

public Gate myGate;
public int myIndex = 0;
public void Click() {
myGate.lights[myIndex].enabled = !myGate.lights[myIndex].enabled;
}

This approach is a little less hassle to set up, since you can select all your switches and drag in the Gate to all of them at once; and it’s much easier to migrate to new puzzles when you build them (you only have to assign new Light references in the gate, not to all switches).

OR

B) A reference to the light directly:

public Light myLight;
public void Click() {
myLight.enabled = !myLight.enabled;
}

This approach is a little more direct and straightforward. Switch.cs doesn’t rely on Gate.cs at all, but because they both look at the same Light object, they can still share data (the ‘enabled’ states).

Sidenote: This code assumes that Gate.lights is a Light[ ] array, which I recommend. If you keep it as a GameObject[ ] array, use .SetActive(x) instead of .enabled = x