1
\$\begingroup\$

What I want to do is something more or less very simple. The main bool flag lockDoors control all the doors and this is working fine now. But now I want to add a flag to each individual door so I can change the door lock state for each specific door. And if I change the lockDoors state it will change all the doors except if I changed some individuals.

I tried to add a new class name DoorControl and made it also Serializable but not sure if this is the way and how to do it.

Example of how it should look like in the Inspector:

lockDoors checkbox here (This is the flag for all the doors) and then:

Door1
   checkbox here
Door2
   checkbox here
Door3
   checkbox here

So I can keep controlling the whole doors or each door individual.

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class DoorsLockManager : MonoBehaviour
{
    [System.Serializable]
    public class DoorControl
    {
        public bool doorLock;
    }

    public bool lockDoors = false;
    public List<HoriDoorManager> _doors = new List<HoriDoorManager>();
    public DoorControl[] doorscontrol;

    private bool[] doorsLocks;
    private Renderer rend;
    private Shader unlitcolor;
    private List<GameObject> DoorShieldFXLocked = new List<GameObject>();


    private void Start()
    {
        DoorShieldFXLocked = GameObject.FindGameObjectsWithTag("DoorShield").ToList();
        unlitcolor = Shader.Find("Unlit/ShieldFX");

        var doors = GameObject.FindGameObjectsWithTag("Door");
        foreach (var door in doors)
        {
            _doors.Add(door.GetComponent<HoriDoorManager>());
        }

        doorscontrol = new DoorControl[_doors.Count];

        ChangeDoorsLockStates();
    }

    private void Update()
    {
        ChangeDoorsLockStates();
    }

    private void ChangeDoorsLockStates()
    {
        for (int i = 0; i < DoorShieldFXLocked.Count; i++)
        {
            if (lockDoors == true)
            {
                ChangeColors(Color.red, Color.green, i);
            }
            else
            {
                ChangeColors(Color.red, Color.green, i);
            }
        }

        for (int x = 0; x < _doors.Count; x++)
        {
            if (lockDoors == true)
            {
                LockDoor(x);
            }
            else
            {
                UnlockDoor(x);
            }
        }
    }

    private void ChangeColors(Color32 lockedColor, Color32 unlockedColor, int index)
    {
        var renderer = DoorShieldFXLocked[index].GetComponent<Renderer>();
        renderer.material.shader = Shader.Find("Unlit/ShieldFX");

        if (lockDoors == true)
        {
            renderer.material.SetColor("_MainColor", lockedColor);
        }
        else
        {
            renderer.material.SetColor("_MainColor", unlockedColor);
        }
    }

    public void LockDoor(int doorIndex)
    {
        _doors[doorIndex].ChangeLockState(true);
    }
    public void UnlockDoor(int doorIndex)
    {
        _doors[doorIndex].ChangeLockState(false);
    }
}

And this script is attached to each door:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class HoriDoorManager : MonoBehaviour
{   
    private List<DoorHori> doors = new List<DoorHori>();
    private bool doorLockState;

    private void Start()
    {
        if (transform.parent != null)
        {
            Transform parent = transform.parent;
            var children = parent.GetComponentsInChildren<Transform>();

            if(children != null)
            {
                foreach (Transform door in children)
                {
                    if (door.name == "Door_Left" || door.name == "Door_Right")
                        doors.Add(door.GetComponent<DoorHori>());
                }
            }
        }
    }

    void OnTriggerEnter()
    {
        if (doorLockState == false)
        {
            if (doors != null)
            {
               for(int i =0; i < doors.Count; i++)
                {
                    doors[i].OpenDoor();
                }
            }
        }
    }

    public void ChangeLockState(bool lockState)
    {
        doorLockState = lockState;
    }
}
\$\endgroup\$
  • 1
    \$\begingroup\$ So you basically want a bool for each door that overrides your "master" bool that controlls all doors? Did I understand that correctly? \$\endgroup\$ – TehMightyPotato Mar 14 at 9:47
  • \$\begingroup\$ @TehMightyPotato You undestood it right. a bool for each door and to keep the master bool. So I can keep also change all the doors. The idea is to be able to change each door and also to change all the doors using the "master". \$\endgroup\$ – Dubi Duboni Mar 14 at 16:42
  • \$\begingroup\$ @TehMightyPotato You can look at this link on my question there about it too with more details including a screenshot of a door structure example. I don't want to use editor script type or to draw the bools flags. Justl ike you commented above. stackoverflow.com/questions/55111177/… \$\endgroup\$ – Dubi Duboni Mar 14 at 17:07
1
\$\begingroup\$

Okay I just did a mockup of what I think it is you want:

//each door has a DoorControl object which holds the bool variables and handles 
//changing the variables
[System.Serializable]
public class DoorControl
{
    public bool doorLock;
    public bool doorLockOverride;

    public DoorControl(bool doorLock = true, bool doorLockOverride = false)
    {
        this.doorLock = doorLock;
        this.doorLockOverride = doorLockOverride;
    }

    public void SetDoorLockState(bool val)
    {
        doorLock = val;
    }
}


public class Door : MonoBehaviour
{
    public DoorControl thisDoorControl;

    private void Start()
    {
        thisDoorControl = new DoorControl();
    }

    private void Update()
    {
        if (thisDoorControl.doorLockOverride)
        {
            OpenDoor();
            return;
        }
        if (thisDoorControl.doorLock)
        {
            OpenDoor();
        }
        else
        {
            CloseDoor();
        }
    }

    private void OpenDoor()
    {
        //open your door
    }

    private void CloseDoor()
    {
        //close your door
    }
}

You could then reference each doors DoorControl in your manager class and stuff it into a List<DoorControl> or an DoorControl[] array like this:

public class DoorManager : MonoBehaviour
{
    public List<Door> doors = new List<Door>();
    public List<DoorControl> doorControls = new List<DoorControl>();

    //this is just to initialize the list with values from all the doors. You could 
    //assign those directly in the inspector
    private void Start()
    {
        foreach(var door in doors)
        {
            doorControls.Add(door.thisDoorControl);
        }
    }

    public void ChangeAllLockOverrides(bool val)
    {
        foreach(var door in doorControls)
        {
            door.doorLockOverride = val;
        }
    }
}

The manager then looks like this in the inspector: Unity screenshot

Keep in mind that this will open/close the door every frame because I call it in Update. This is no good solution and you should not copy paste this if you plan to keep your performance as high as possible. I hope this points you in the right direction.

\$\endgroup\$
1
\$\begingroup\$

It's been a while since I used Unity since I moved to UE4, but since no one else is answering, I will try.

I think in this case you should "turn around" the control from doors "asking" about a boolean, and instead, have each door have an individual bool for them. Then, a switch, lever or whatever you are using would have an inspector field "Door to open" of type Door of course. And when you use that switch, you call this door's method to open them.

Obviously, to future proof the game you might use an array of fields so you can open more than one door with one switch if you so desire.

Another way, possibly closer to what you want is this.

A door controller class has the main bool, and an array of bools for each doors. Each door checks the main bool and specific one. And every lever or switch has a variable called "doors index" of type int. Then on usage you would do something along this pseudo-code:

OnLeverUsed{ DoorController->doorsOpened[doors index] = true; }

I hope this answers your question :)

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.