Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Checking Multiple Bool States for Puzzle

Discussion in 'Scripting' started by Kiesco91, Sep 30, 2021.

  1. Kiesco91

    Kiesco91

    Joined:
    Aug 20, 2018
    Posts:
    80
    Hello,

    I have 5 switches, each switch has the same "Switch" script attached basically saying if switch is down, Bool = true. if Switch is up, Bool = False.

    I then want a puzzle where the switches need to be in a sequence to open a door (Example if switch 1, 3, 5 are true, door opens). I'm not sure how to implement this. I was thinking along the lines of the below (Coding might not be perfect, in a rush)

    Code (CSharp):
    1. public GameObject Switch1;
    2. public GameObject Switch2;
    3. public GameObject Switch3;
    4. public GameObject Switch4;
    5. public GameObject Switch5;
    6.  
    7. public GameObject orangeDoor;
    8.  
    9. public void doorOpen()
    10. {
    11. if (Switch1=true && Switch3=true && Switch5=true)
    12. {
    13. orangeDoor.SetActive(false);
    14. }
    15. else
    16. {
    17. orangeDoor.SetActive(true);
    18. }
    19. }
    i realize this wont work as im not checking the Bool for any of the switches but i feel im on the right lines with this idea. Im not sure how to call the Bool of multiple gameObjects and the fact they all have the same "Switch" script, if this will read the Bool from one of the switches and not all of them individually.
     
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    Instead of storing references to GameObjects, store references to your Switch component and then check the switch.isTurnedOn boolean or whatever it's called in that script. Then the rest of your logic is sound, except you need == not = in comparisons.
     
  3. SunnyValleyStudio

    SunnyValleyStudio

    Joined:
    Mar 24, 2017
    Posts:
    67
    Hey!

    How about something like this:
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class DoorSwitch : MonoBehaviour
    7. {
    8.     private bool switchState;
    9.  
    10.     public bool SwitchState
    11.     {
    12.         get { return switchState; }
    13.         private set {
    14.             switchState = value;
    15.             StateChanged?.Invoke();
    16.         }
    17.     }
    18.  
    19.     /// <summary>
    20.     /// A way to autoopen the doors when you modify the state
    21.     /// </summary>
    22.     public event Action StateChanged;
    23.  
    24.     public void Toggle()
    25.         => SwitchState = !SwitchState;
    26. }
    27.  
    28. public class Door : MonoBehaviour
    29. {
    30.     public bool Locked { get; private set; } = true;
    31.  
    32.     [SerializeField]
    33.     private List<DoorSwitchPreset> doorSwitches;
    34.  
    35.     /// <summary>
    36.     /// Connect event of the switch being toggled with door check.
    37.     /// </summary>
    38.     private void Start()
    39.     {
    40.         foreach (DoorSwitchPreset doorSwitch in doorSwitches)
    41.         {
    42.             doorSwitch.SwitchReference.StateChanged += TryOpeningTheDoor;
    43.         }
    44.     }
    45.  
    46.     /// <summary>
    47.     /// Method responsible for checking the switches
    48.     /// </summary>
    49.     public void TryOpeningTheDoor()
    50.     {
    51.         foreach (DoorSwitchPreset doorSwitch in doorSwitches)
    52.         {
    53.             if(doorSwitch.IsSwitchStateCorrect() == false)
    54.             {
    55.                 Locked = true;
    56.                 return;
    57.             }
    58.         }
    59.         Locked = false;
    60.     }
    61. }
    62.  
    63. /// <summary>
    64. /// Helper class to preset the switches and the correct result for each door
    65. /// </summary>
    66. [Serializable]
    67. public class DoorSwitchPreset
    68. {
    69.     [SerializeField]
    70.     private DoorSwitch switchReference;
    71.  
    72.     public DoorSwitch SwitchReference
    73.     {
    74.         get { return switchReference; }
    75.     }
    76.  
    77.     [SerializeField]
    78.     private bool correctState;
    79.  
    80.     public bool CorrectState
    81.     {
    82.         get { return correctState; }
    83.     }
    84.  
    85.     public bool IsSwitchStateCorrect()
    86.         => SwitchReference.SwitchState == CorrectState;
    87. }
    *Be sure to place each DoorSwitch and Door classes in separate scripts. I haven't tested this code but it should give you some idea how to structure it.

    I hope it helps!
     
  4. Kiesco91

    Kiesco91

    Joined:
    Aug 20, 2018
    Posts:
    80
    Hey, so ive taken a break from this project and now ready to dive back in. ive tried the way SunnyValleyStudio suggested but with no luck so ive gone back to my original method.

    here is my switch script. I have 5 switches all with their own individual Script (switch1, switch2 etc) all identical except for script name and the bool number is different (on1, on2, on3 etc)

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Switch1 : MonoBehaviour
    6. {
    7.     public GameObject _Switchon;
    8.     public GameObject _Switchoff;
    9.     public bool on1 = false;
    10.  
    11.     private void OnTriggerStay(Collider plyr)
    12.     {
    13.         if (plyr.tag == "Player" && Input.GetKeyDown(KeyCode.E) && !on1)
    14.             {
    15.             _Switchoff.SetActive(false);
    16.             _Switchon.SetActive(true);
    17.             on1 = true;
    18.         }
    19.         else if (plyr.tag == "Player" && Input.GetKeyDown(KeyCode.E) && on1)
    20.         {
    21.             _Switchoff.SetActive(true);
    22.             _Switchon.SetActive(false);
    23.             on1 = false;
    24.         }
    25.     }
    26. }
    this works and is switching the bool to on/off fine.

    this is my switch manager script. (the SwitchHolder is just an empty game object on each switch with the Switch script attached to it) :

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class SwitchDoors : MonoBehaviour
    6. {
    7.     public GameObject Switch1;
    8.     public GameObject Switch2;
    9.     public GameObject Switch3;
    10.     public GameObject Switch4;
    11.     public GameObject Switch5;
    12.  
    13.     public GameObject orangeDoor;
    14.     public GameObject purpleDoor;
    15.  
    16.     void Start()
    17.     {
    18.         bool on1 = GameObject.Find("SwitchHolder").GetComponent<Switch1>().on1;
    19.         bool on2 = GameObject.Find("SwitchHolder (1)").GetComponent<Switch2>().on2;
    20.         bool on3 = GameObject.Find("SwitchHolder (2)").GetComponent<Switch3>().on3;
    21.         bool on4 = GameObject.Find("SwitchHolder (3)").GetComponent<Switch4>().on4;
    22.         bool on5 = GameObject.Find("SwitchHolder (4)").GetComponent<Switch5>().on5;
    23.     }
    24.  
    25.     public void orangedoorOpen()
    26.     {
    27.         if (Switch1 == true && Switch2 == true && Switch4 == true)
    28.         {
    29.             orangeDoor.SetActive(false);
    30.         }
    31.         else
    32.         {
    33.             orangeDoor.SetActive(true);
    34.         }
    35.     }
    36.  
    37.     public void purpledoorOpen()
    38.     {
    39.         if (Switch1 == true && Switch3 == true && Switch5 == true)
    40.         {
    41.             purpleDoor.SetActive(false);
    42.         }
    43.         else
    44.         {
    45.             purpleDoor.SetActive(true);
    46.         }
    47.     }
    48. }
    each switch game object has the switch holder with the correct script attached.

    although I can see in the inspector the correct bools are on/off, it isn't turning the doors on and off.

    any help appreciated :)
     
  5. RadRedPanda

    RadRedPanda

    Joined:
    May 9, 2018
    Posts:
    1,593
    To answer your specific problem you asked, you never call
    orangedoorOpen()
    or
    purpledoorOpen()
    anywhere, so that code never gets called. The "quick and dirty" way to just fix this is to call those two methods in an
    Update()
    loop.

    Here's a version that's not as complicated as SunnyValley's, but definitely better than what you have, and I suggest reading through it and understanding what's happening.

    This code is alright, I would rather have the input stuff in the player. You don't need a separate script for each Switch, just use the one for all of them. I cleaned it up a little to make it nicer to read.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Switch : MonoBehaviour
    6. {
    7.     public GameObject _Switchon;
    8.     public GameObject _Switchoff;
    9.     public bool on = false;
    10.     private void OnTriggerStay(Collider plyr)
    11.     {
    12.         if (plyr.tag == "Player" && Input.GetKeyDown(KeyCode.E))
    13.             {
    14.             on = !on;
    15.             _Switchon.SetActive(on);
    16.             _Switchoff.SetActive(!on);
    17.         }
    18.     }
    19. }
    I don't believe you need a SwitchManager to handle all the code for your switches, you can just have code for your doors. You can have some code like this in your doors which hold references to which switches you need.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Door : MonoBehaviour
    6. {
    7.     public Switch[] Switches;
    8.  
    9.     void Update()
    10.     {
    11.         bool state = true;
    12.         foreach (Switch switch in Switches)
    13.         {
    14.             if (!switch.on)
    15.                 state = false;
    16.         }
    17.         gameObject.SetActive(state);
    18.     }
    19. }
    Now by no means is this optimal, but hopefully it will show you the next step you can take your code in.
     
  6. Kiesco91

    Kiesco91

    Joined:
    Aug 20, 2018
    Posts:
    80
    Hi RadRedPanda,

    So I tried what you first suggested in setting an update and I have this.
    Code (CSharp):
    1.  
    2. void Start()
    3.     {
    4.         bool on1 = GameObject.Find("SwitchHolder").GetComponent<Switch1>().on1;
    5.         bool on2 = GameObject.Find("SwitchHolder (1)").GetComponent<Switch2>().on2;
    6.         bool on3 = GameObject.Find("SwitchHolder (2)").GetComponent<Switch3>().on3;
    7.         bool on4 = GameObject.Find("SwitchHolder (3)").GetComponent<Switch4>().on4;
    8.         bool on5 = GameObject.Find("SwitchHolder (4)").GetComponent<Switch5>().on5;
    9.  
    10.         orangeDoor.SetActive(true);
    11.         purpleDoor.SetActive(true);
    12.     }
    13.  
    14.     void Update()
    15.     {
    16.         if (Switch1 == true && Switch2 == true && Switch4 == true)
    17.         {
    18.             orangedoorOpen();
    19.         }
    20.         else
    21.         {
    22.             orangeDoorClosed();
    23.         }
    24.  
    25.         if (Switch1 == true && Switch3 == true && Switch5 == true)
    26.         {
    27.             purpledoorOpen();
    28.         }
    29.         else
    30.         {
    31.             purpleDoorClosed();
    32.         }
    33.     }
    34.  
    35.     public void orangedoorOpen()
    36.     {
    37.             orangeDoor.SetActive(false);
    38.     }
    39.  
    40.     public void purpledoorOpen()
    41.     {
    42.             purpleDoor.SetActive(false);
    43.     }
    44.  
    45.     public void orangeDoorClosed()
    46.     {
    47.         orangeDoor.SetActive(true);
    48.     }
    49.  
    50.     public void purpleDoorClosed()
    51.     {
    52.         purpleDoor.SetActive(true);
    53.     }
    54. }
    55.  
    whenever I play the game, the doors are automatically SetActive to false now which is annoying me even more because I can't see where im calling them to be false except when open and they should only open when the code is correct.

    I've gone through your code trying to break down what you're suggesting but I don't get switch states. ive no idea where im setting the switch states or what code I want them to be in for it to be unlocked.