Почему флаг цвета дверей / дверей все время имеет значение true / false и все время изменяется между true и false? - PullRequest
0 голосов
/ 02 ноября 2019

Этот сценарий прикреплен к двери:

Даже если для переменной doorLockState установлено значение true, разрешено значение true в редакторе, а дверь должна быть красного цвета, дверь имеет зеленый цвет с использованием точки останова переменной состояния внутри. ColorDoors - это изменение между красным и зеленым без остановок, если состояние истинно, затем оно ложно, но в редакторе оно всегда проверяется как истинное:

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

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

    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.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; }
    }

    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;
        }
    }
}

Снимок экрана конструктора дверей в иерархии и сценария вИнспектор:

Door Constructor

Для тега объекта Horizontal_Doors_Kit установлено значение Door.

И это сценарий редактора, который должен позволить мне контролироватьдвери, но здесь также есть проблема, поскольку в редакторе не отображаются все двери:

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()
    {
        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();
    }
}

Снимок экрана инспектора сценариев редактора:

Doors Editor

Он показывает две переменные Global Lock State, но также должен перечислить 12 дверей.

  • Первая проблема состояния двери / с:все время разблокирован зеленым цветом.

  • Вторая проблема заключается в том, почему он не перечисляет все двери, поэтому я могу контролировать каждую / все двери либо в редакторе, либо во время выполнения?

И скрипт DoorsLockManager:

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

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.doorLockState = _globalLockState;
            }
        }
    }

    private void Awake()
    {
        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>();
        }
    }
}

1 Ответ

1 голос
/ 03 ноября 2019

В настоящее время ваш список Doors обновляется только при вызове Awake() в вашем DoorsLockManager (и недоступном из инспектора), что означает, что список всегда пуст за пределами времени выполнения. Изменение этого параметра должно позволить отображать список в инспекторе при редактировании.

Внесение следующих незначительных изменений в DoorsLockManager.cs :

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>();
    }
}

и добавление следующегок началу метода OnInspectorGUI() в DoorsLockManagerEditor.cs :

if (GUILayout.Button("Update Door List"))
{
    ((DoorsLockManager)target).UpdateDoors();
}

следует добиться этого, предоставив кнопку для обновления списка при необходимости.

Individualи состояния глобальной блокировки теперь должны быть функциональными, однако только один из двух переключателей Global Lock State работает правильно, это можно исправить, удалив base.OnInspectorGUI(); из метода OnInspectorGUI() в DoorsLockManagerEditor.cs илидобавив [HideInInspector] до [SerializeField] private bool _globalLockState; в DoorsLockManager.cs .

В настоящее время HoriDoorManager.cs обновит только свои соответствующие двери во время выполнения как метод ColorDoorsвызывается только в Awake() и Update(). Вместо этого это можно сделать для обновления всякий раз, когда изменяется doorLockState bool, изменив свойство GetLockState следующим образом:

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

и присвоив этому свойству вместо вспомогательной переменной в свойстве GlobalLockStateиз DoorsLockManager.cs (замена строки 28: door.doorLockState = _globalLockState; на door.GetLockState = _globalLockState;).


Редактировать: Это немного быстрый взлом, но с добавлением следующего к DoorsLockManager.cs :

public void UpdateColors()
{
    foreach (var door in Doors)
    {
        door.GetLockState = door.GetLockState;
    }
}

и следующее до OnInspectorGUI() в DoorsLockManagerEditor.cs под другой кнопкой:

    if (GUILayout.Button("Update Door Colors"))
    {
        ((DoorsLockManager)target).UpdateColors();
    }

должно разрешатьвы должны сообщить дверцам, чтобы они обновляли свои цвета у инспектора вручную.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...