0
\$\begingroup\$

The goal is to change the doors lock state in the editor mode and also in run time. It's not working either in run time or editor mode.

The problem is in the HoriDoorManager in the Update. The method ColorDoors is calling in the Update all the time and when I'm changing the doors lock mode to be locked and the variable state is true after some frames in the Update it's changing the state variable to be false and therefore the doors all the time in green color in unlocked mode. I can't figure out why.

This is the HoriDoorManager this script is attached to each door :

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

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

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

    private void ColorDoors(Color red, Color green, bool state)
    {
        // This method should not be inside the 
        // OnTriggerEnter but to be called once
        // Maybe in the Awake or in Start to think
        // And solve it first !!!!!

        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.sharedMaterial.shader = Shader.Find("Unlit/ShieldFX");

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

    public bool GetLockState
    {
        get { return doorLockState; }
        set
        {
            doorLockState = value;
            ColorDoors(Color.red, Color.green, doorLockState);
        }
    }

    private void LockState(bool state)
    {
        var collider = gameObject.GetComponent<BoxCollider>();

        if (state == false)
        {
            collider.size = new Vector3(2.3f, 2.736307f, 2.5f);
            collider.center = new Vector3(0, 1.378154f, 0);
            collider.transform.localPosition = new Vector3(-1.57f, 0, -2.98f);
            collider.isTrigger = true;
        }
        else
        {
            collider.size = new Vector3(2.3f, 2.736307f, 3);
            collider.center = new Vector3(0, 1.378154f, 0);
            collider.transform.localPosition = new Vector3(-1.57f, 0, -2.98f);
            collider.isTrigger = false;
        }
    }
}

This script is attached to one empty GameObject :

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

[ExecuteInEditMode]
public class DoorsLockManager : MonoBehaviour
{
    [HideInInspector]
    public List<HoriDoorManager> Doors = new List<HoriDoorManager>();

    // The global state
    [SerializeField] private bool _globalLockState;

    // During runtime use a property instead
    public bool GlobalLockState
    {
        get { return _globalLockState; }
        set
        {
            _globalLockState = value;

            // apply it to all doors
            foreach (var door in Doors)
            {
                // now you would need it public again
                // or use the public property you had there
                door.GetLockState = _globalLockState;
            }
        }
    }

    private void Awake()
    {
        UpdateDoors();
    }

    public void UpdateDoors()
    {
        var doors = GameObject.FindGameObjectsWithTag("Door");
        Doors = new HoriDoorManager[doors.Length].ToList();

        for (int i = 0; i < doors.Length; i++)
        {
            Doors[i] = doors[i].GetComponent<HoriDoorManager>();
        }
    }
}

And the editor script :

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(DoorsLockManager))]
public class DoorsLockManagerEditor : Editor
{
    private SerializedProperty _doors;
    private SerializedProperty _globalLockState;

    private bool shouldOverwrite;

    private void OnEnable()
    {
        _doors = serializedObject.FindProperty("Doors");
        _globalLockState = serializedObject.FindProperty("_globalLockState");
    }

    public override void OnInspectorGUI()
    {
        //if (GUILayout.Button("Update Door List"))
        //{
        //  ((DoorsLockManager)target).UpdateDoors();
        //}

        base.OnInspectorGUI();

        serializedObject.Update();

        shouldOverwrite = false;

        // Begin a change check here
        EditorGUI.BeginChangeCheck();
        EditorGUILayout.PropertyField(_globalLockState);
        if (EditorGUI.EndChangeCheck())
        {
            // overwrite only once if changed
            shouldOverwrite = true;
        }

        for (int i = 0; i < _doors.arraySize; i++)
        {
            var door = _doors.GetArrayElementAtIndex(i);

            // if door == null the script itself has an error since it can't even find the SerializedProperty
            if (door == null)
            {
                EditorGUILayout.HelpBox("There was an error in the editor script!\nPlease check the log", MessageType.Error);
                Debug.LogError("Couldn't get door property", target);
                return;
            }

            if (door.objectReferenceValue == null) continue;

            var serializedDoor = new SerializedObject(door.objectReferenceValue);

            var lockState = serializedDoor.FindProperty("doorLockState");

            serializedDoor.Update();

            if (lockState == null)
            {
                EditorGUILayout.HelpBox("There was an error in the editor script!\nPlease check the log", MessageType.Error);
                Debug.LogError("Couldn't get lockState property", target);
                return;
            }

            // HERE OVERWRITE
            if (shouldOverwrite)
            {
                lockState.boolValue = _globalLockState.boolValue;
            }
            else
            {
                EditorGUILayout.PropertyField(lockState, new GUIContent("Door " + i + " Lockstate"));
            }

            serializedDoor.ApplyModifiedProperties();
        }

        serializedObject.ApplyModifiedProperties();
    }
}

This is a screenshot showing one of the doors structure in the Hierarchy :

Door

And a screenshot of the doors lock manager : The door/s all the time green even if I change in the Inspector the mode to be locked it's never turn red :

Door

\$\endgroup\$

Your Answer

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

Browse other questions tagged or ask your own question.