【问题标题】:Unity Editor - C#: Why does my list reset to null OnEnable?Unity Editor - C#:为什么我的列表重置为 null OnEnable?
【发布时间】:2019-02-02 15:25:00
【问题描述】:

我正在尝试制作一个自定义统一编辑器,但由于某种原因,每次我关闭窗口并再次打开它时,我的列表都会重置为 null。

我试图通过将键和值分成两个单独的列表OnDisable 来保存字典中的数据,然后通过组合列表重新创建字典OnEnable。但是每次调用 OnEnable 时,我的列表中都会得到一个空值...

这是代码的示例。

public Dictionary<string, string> myDictionary = new Dictionary<string, string>();

[SerializeField]
public List<string> listOfDictionaryKeys;


    private void OnEnable()
    {
        // this always returns null
        Debug.Log(listOfDictionaryKeys.Count);

    }

    private void OnDisable()
    {
        // this successfully saves the keys to the list
        listOfDictionaryKeys = (myDictionary.Keys).ToList();

    }

有人知道为什么我会丢失我的列表数据吗?我没有在检查器中设置任何值,它们都是由代码设置和保存的。

【问题讨论】:

  • 最好是你总是初始化像public List&lt;string&gt; listOfDictionaryKeys = new List&lt;string&gt;(); 这样的列表,这是整个代码吗,因为我看不到你在OnEnable 的哪个位置重新创建了列表...
  • @derHugo 我在onDisableOnEnable 中填充列表,我尝试从中获取计数以查看它是否为空并且它总是返回空。我将public List&lt;string&gt; listOfDictionaryKeys; 更改为public static List&lt;string&gt; listOfDictionaryKeys = new List&lt;string&gt;();,现在当我关闭并打开窗口时,列表可以正常工作,但是,每当脚本重新编译时,我会再次丢失列表数据
  • 我不明白你为什么只在OnDisable 中填充它?
  • @derHugo 因为该列表只是尝试保存我的字典条目的一种方式,在OnDisable 我的字典被擦除为空之后,所以我试图保存我字典中的所有数据进入 2 个列表 OnDisable(在键列表和一个值列表上),然后将相同数据从 2 个列表重新加载回 OnEnable 中的字典。但是我的列表数据也被清除了,我不知道为什么
  • 你的问题不是很清楚。我猜会发生什么,但必须确切了解您的课程设置和编辑器脚本。此外,实际了解您填写该列表的方式和位置也会有很大帮助。还有你在哪里填字典?

标签: c# list unity3d


【解决方案1】:

UnityEditor 是一个(伟大的工具)棘手的野兽,它运行自己的回调循环,编辑器内的序列化和反序列化可能有点混乱。

有时,unity 会忽略对象的构造函数所做的任何事情,并在下一次更新时用默认值覆盖它。我想当对象的检查器在预期列表的位置找到 null 时会对其进行初始化,但是如果您不将新的序列化表单与场景一起保存,它将保持为 null,并且当 OnEnable 发生时将为 null (反序列化后),除非它与场景一起保存。

我没有完全掌握这个过程,但这就是我的想象。

要快速解决问题,请执行以下操作:

private void OnEnable()
{
    if (listOfDictionaryKeys==null) listOfDictionaryKeys=new List<string>();
    // this always returns null
    Debug.Log(listOfDictionaryKeys.Count);

}

这样你就不会在它存在时不小心删除它

【讨论】:

    【解决方案2】:

    从您的问题中我不太明白 OnEnableOnDisable 是您的编辑器脚本的一部分还是组件本身。

    如果是后者:

    OnEnable 在组件从禁用状态变为启用状态时调用,不是在它在检查器中获得焦点时调用。同样的方式OnDisabled在组件或相应的游戏对象被禁用时被调用,不是如果它失去焦点。

    如果您想要对检查器中获得和失去焦点做出反应,则必须是检查器脚本本身的OnEnableOnDisable。例如

    [CustomEditor(typeof(XY)]
    public class XYEditor : Editor
    {
        XY _target;
        SerializedProperty list;
    
        // Called when the class gains focus
        private void OnEnable()
        {
            _target = (XY) target;
    
            //Link the SerializedProperty
            list = serializedObject.FindProperty("listOfDictionaryKeys");
        }
    
        public override void OnInpectorGUI()
        {
            //whatever your inspector does
        }
    
        // Called when the component looses focus
        private void OnDisable()
        {
            serializedObjet.Update();
    
            // empty list
            list.ClearArray;
    
            // Reading access to the target's fields is okey 
            // as long as you are sure they are set at the moment the editor is closed
            foreach(var key in _target.myDoctionary.keys)
            {
                list.AddArrayElementAtIndex(list.arraySize);
                var element = list.GetArrayElementAtIndex(list.arraySize - 1);
                element.stringValue = key;
            }
    
            serialzedObject.ApplyModifiedProperties;
        }
    }
    

    我也看不到你在哪里填充字典,因为你说它没有发生在检查器中。当 mixonbSerializedProperty 直接访问字段时,这可能是个问题。

    【讨论】:

    • 帖子中的代码是编辑器脚本的一部分。通过进入自定义编辑器窗口,字典被填充到相同的脚本中。我将功能放在OnEnableOnDisable 中,因为它们是关闭/打开检查器窗口时调用的第一个也是最后一个方法。现在,当我关闭自定义编辑器窗口并重新打开它时,一切正常,当调用 OnDisable 时,字典被复制到 2 个列表中,然后这 2 个列表在 OnEnable 中重新填充字典。但是当我的编辑器脚本重新编译时,我再次丢失数据并获得空列表
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-15
    • 1970-01-01
    • 2021-02-12
    • 2017-02-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多