C# 为什么在运行游戏时,门锁定状态会覆盖并设置为false?

C# 为什么在运行游戏时,门锁定状态会覆盖并设置为false?,c#,unity3d,C#,Unity3d,当游戏已经运行时,它工作正常。我可以更改每个门锁状态。但在运行游戏之前,我设置了一个或多个要锁定的门(选中将标志设置为true),然后运行游戏,它将所有的门都更改为false unlocked 我想,如果我在运行游戏之前也设置了doors lock状态,它会在游戏运行时保持这种变化 第一个脚本只有一行: using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine;

当游戏已经运行时,它工作正常。我可以更改每个门锁状态。但在运行游戏之前,我设置了一个或多个要锁定的门(选中将标志设置为true),然后运行游戏,它将所有的门都更改为false unlocked

我想,如果我在运行游戏之前也设置了doors lock状态,它会在游戏运行时保持这种变化

第一个脚本只有一行:

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

public class DoorsLockManager : MonoBehaviour
{
    public List<HoriDoorManager> Doors = new List<HoriDoorManager>();
}
使用系统集合;
使用System.Collections.Generic;
使用System.Linq;
使用UnityEngine;
公共类DoorsLockManager:MonoBehavior
{
公共列表门=新列表();
}
第二个脚本控制门:

using UnityEditor;

[CustomEditor(typeof(DoorsLockManager))]
public class DoorsLockManagerEditor : Editor
{
    DoorsLockManager _manager;

    public override void OnInspectorGUI()
    {
        _manager = (DoorsLockManager)target;

        base.OnInspectorGUI();

        if (_manager.Doors.Count <= 0)
            return;
        for (var i = 0; i < _manager.Doors.Count; i++)
        {
            if (_manager.Doors[i] == null)
                continue;

            _manager.Doors[i].GetLockState = EditorGUILayout.Toggle("Door " + i + " Lockstate", _manager.Doors[i].GetLockState);
        }
    }
}
使用UnityEditor;
[CustomEditor(typeof(DoorsLockManager))]
公共类DoorsLockManagerEditor:编辑器
{
门牌经理(DoorsLockManager);;
公共覆盖无效OnInspectorGUI()
{
_经理=(DoorsLockManager)目标;
base.OnInspectorGUI();
如果(_manager.Doors.Count您是否尝试了DoorsLockManagerEditor

编辑器似乎没有保留初始值。

您在门SlockManager编辑器中尝试过吗


编辑器似乎没有保留初始值。

属性是不可序列化的。

您永远不应该在编辑器脚本中更改它们,因为它们没有序列化=>永远不会保存,并且始终具有默认值

如果它是属性类似,则它将不起作用

public bool GetLockState
{
    get { return doorLockState; }
    set { doorLockState = value; }
}
如果你的
doorLockState
public
的话,为什么还要使用这个呢

问题在于,这不会将更改的字段
doorLockState
标记为“脏”

但是,您应该不要使用
EditorUtility.SetDirty
,因为:

从5.3开始,随着多场景编辑的引入,此功能不应再用于修改场景中的对象。相反,在对对象进行更改之前,应使用
Undo.RecordObject
。这将对象的场景标记为,并在编辑器中提供撤销条目.'


相反,在编辑器脚本中,您必须更改
doorLockState
的值

如果它位于
private
位置,则必须添加
[SerializeField]

[SerializeField] private bool doorLockState;
但在您的情况下,它似乎是公开的,所以它是自动序列化的

而不是在编辑器脚本中直接操作值

开始时它看起来更复杂,但这会自动处理诸如撤消/重做和将内容标记为脏(从而保存更改)之类的事情,因此您不必处理其他任何事情:

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

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

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        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;

            // FindPropertyRelative seems not to work for MonoBehaviour classes
            // so we have to use this hack around
            var serializedDoor = new SerializedObject(door.objectReferenceValue);

            // If it's public no worry anyway
            // If it's private still works since we made it a SerializeField
            var lockState = serializedDoor.FindProperty("doorLockState");

            // Fetch current values into the serialized "copy"
            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;
            }

            // for the PropertyField there is 
            // no return value since it automatically uses
            // the correct drawer for the according property
            // and directly changes it's value
            EditorGUILayout.PropertyField(lockState, new GUIContent("Door " + i + " Lockstate"));

            // or alternatively
            //lockState.boolValue = EditorGUILayout.Toggle("Door " + i + " Lockstate", lockState.boolValue);

            // Write back changes, mark as dirty if changed
            // and add a Undo history entry
            serializedDoor.ApplyModifiedProperties();
        }
    }
}
[CustomEditor(typeof(DoorsLockManager))]
公共类DoorsLockManagerEditor:编辑器
{
私有财产门;
私有void OnEnable()
{
_doors=serializedObject.FindProperty(“doors”);
}
公共覆盖无效OnInspectorGUI()
{
base.OnInspectorGUI();
对于(int i=0;i<\u doors.arraySize;i++)
{
var door=\u doors.GetArrayElementIndex(i);
//如果door==null,脚本本身就有一个错误,因为它甚至找不到SerializedProperty
如果(门==null)
{
EditorGUILayout.HelpBox(“编辑器脚本中有错误!\n请检查日志”,MessageType.error);
LogError(“无法获取门属性”,目标);
返回;
}
如果(door.objectReferenceValue==null)继续;
//FindPropertyRelative似乎不适用于单一行为类
//所以我们必须使用这个黑客
var serializedDoor=新SerializedObject(door.objectReferenceValue);
//如果是公众的话,不用担心
//如果它是私有的,自从我们将它设置为一个序列化字段后,它仍然有效
var lockState=serializedDoor.FindProperty(“doorLockState”);
//将当前值提取到序列化的“副本”中
序列化ddoor.Update();
if(lockState==null)
{
EditorGUILayout.HelpBox(“编辑器脚本中有错误!\n请检查日志”,MessageType.error);
LogError(“无法获取lockState属性”,目标);
返回;
}
//对于PropertyField,有
//没有返回值,因为它自动使用
//相应属性的正确抽屉
//直接改变它的价值
EditorGUILayout.PropertyField(lockState,新GUIContent(“门”+i+“锁状态”));
//或者
//lockState.boolValue=EditorGUILayout.Toggle(“门”+i+“锁状态”,lockState.boolValue);
//写回更改,如果更改,则标记为脏
//并添加撤消历史记录条目
serializedDoor.ApplyModifiedProperties();
}
}
}


(当然,该值仅在InspectorGUI上更新
,因此,如果您打开了多个Inspector选项卡,则仅在悬停时更新该值)

属性是不可序列化的

您永远不应该在编辑器脚本中更改它们,因为它们没有序列化=>永远不会保存,并且始终具有默认值

如果它是属性类似,则它将不起作用

public bool GetLockState
{
    get { return doorLockState; }
    set { doorLockState = value; }
}
如果你的
doorLockState
public
的话,为什么还要使用这个呢

问题在于,这不会将更改的字段
doorLockState
标记为“脏”

但是,您应该不要使用
EditorUtility.SetDirty
,因为:

从5.3开始,随着Mul的引入