0
\$\begingroup\$

In the DoorsLockManager in the class DoorClass I changed in the editor one of the lockState to true but when running the game they are all change to false including the one I tried to set to true. Not sure why if I set it to true it's changing back to false.

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

[ExecuteInEditMode]
public class DoorsLockManager : MonoBehaviour
{
    [System.Serializable]
    public class DoorClass
    {
        public bool lockState;
    }

    public DoorClass[] doorclass;

    private List<HoriDoorManager> Doors = new List<HoriDoorManager>();

    private void Start()
    {
        var doors = GameObject.FindGameObjectsWithTag("Door");
        doorclass = new DoorClass[doors.Length];

        for (int i = 0; i < doors.Length; i++)
        {
            Doors.Add(doors[i].GetComponent<HoriDoorManager>());
            doorclass[i] = new DoorClass();
            Doors[i].doorLockState = doorclass[i].lockState;        }
    }
}

And the HoriDoorManager script:

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

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

    private void Awake()
    {
        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>());
                }
            }
            ColorDoors(Color.red, Color.green, doorLockState);
        }
    }

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

    private void ColorDoors(Color red, Color green, bool state)
    {
        List<Transform> children = new List<Transform>();

        for (int i = 0; i < doors.Count; i++)
        {
            foreach (Transform child in doors[i].GetComponentsInChildren<Transform>())
            {
                if (child == doors[i].transform)
                    continue;

                var renderer = child.GetComponent<Renderer>();
                renderer.material.shader = Shader.Find("Unlit/ShieldFX");

                if(state == true)
                {
                    renderer.material.SetColor("_MainColor", red);
                }
                else
                {
                    renderer.material.SetColor("_MainColor", green);
                }
            }
        }
    }

    public bool GetLockState
    {
        get { return doorLockState; }
        set { doorLockState = value; }
    }
}
\$\endgroup\$
3
\$\begingroup\$
doorclass = new DoorClass[doors.Length];

This line throws out any lock state information you might have previously had and creates a new array from scratch. So if your plan was to use data you'd authored in the inspector at edit time, you've just lost it.

doorclass[i] = new DoorClass();

This line creates a new instance of the DoorClass type, with default values. The default value of a bool is false. So the value of lockState on this instance is always false,

Your next line then applies this always-false value to the i-th door:

Doors[i].doorLockState = doorclass[i].lockState;

Booleans are a value type, which means when you do this, you're copying the false value from doorclass[i].lockState to Doors[i].doorLockState, not creating a reference from the door to the bool in your array.

Since you never check doorclass[i].lockState again, changing this value in the inspector later won't change the door's behaviour. It still has its own copy of the false value and knows nothing about the DoorClass instance you created for it.

I'm not sure what to tell you about how to fix this, because it's unclear how you expected this to work.

If you meant to author these lock values ahead of time in the Inspector, then you should remove the lines that create a new DoorClass[] array and default instances in Start(), as that throws away anything you wrote at edit time. However, this is a brittle method with no real control over order, and it would be easy for the collection of doors & lock bools to get out of sync and cause errors like an index out of range.

If you meant to populate these lock values procedurally as your level is generated at runtime, then that procedural logic to determine true or false lock states should run before you assign the lock values to the doors, rather than using the default false for all of them.

If you meant to use this collection of bools as a control panel to later change the states of the doors after Start() has run, then you need some code to fire when the i-th door's lock bool has changed and relay that state change to the i-th door. You'd do that differently if you need it to work for editor interaction via the Inspector (which seems to be suggested by the fact you made this array public), versus via code (which I'd assume you'd want to do for systemic gameplay, but I don't see evidence of it in your current sample), so again it's unclear from the current question what solution is appropriate for your needs here.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the comment and the explaining. My main goal is to build a control system in the script DoorsLockManager. The idea is to be able to decide what door will be locked or unlocked before running the game, That's why I used [ExecuteInEditMode]. I want when running the game that some doors will be locked and some unlocked. And also to be able to control the doors lock state while the game is running. But the main idea is to build a control system for the doors lock system including the colors changes(Red locked, Green unlocked). \$\endgroup\$ – Dubi Duboni Mar 25 at 8:54
  • \$\begingroup\$ Make it shorter I want the owner to be able to control the doors lock state before running the game in the editor and after running the game. In both cases to control the doors in the Inspector. After that when I will decide what doors to lock or unlock in the game I will move to the part that give the player to be able to control the doors in the game. \$\endgroup\$ – Dubi Duboni Mar 25 at 9:02
  • 1
    \$\begingroup\$ That looks like a different question than "why doesn't this code work?" and it looks like you have some useful answers already. \$\endgroup\$ – DMGregory Mar 25 at 9:02

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.