c# - Unity 中 HashSet 的自定义检查器

标签 c# unity-game-engine editor hashset

我正在 Unity 中创建 RPG 游戏。最近,我成功地实现了 HashSet 的自定义检查器。但是,有两个主要问题我需要帮助。

1) 使用 Itemslot.cs 对预制件/对象上的哈希集进行的更改有效,但只会持续到我退出 Unity 为止。此外,当我对预制件进行更改并将其拖动到场景时,新创建的对象具有其 HashSet,而无需我之前对预制件进行任何更改。

2) 自从实现此功能以来,当我对 .cs 文件进行更改并尝试编译时,编辑器有时会无限期地卡住。

它的外观:

enter image description here

Itemslot.cs

public class Itemslot : MonoBehaviour, IDropHandler, IPointerEnterHandler, IPointerExitHandler
{
[System.Serializable]
public class HashSetItemType : HashSet<GlobalEnums.ItemType> { }
public HashSetItemType typeAllowed = new HashSetItemType();

[System.Serializable]
public class HashSetClassType : HashSet<GlobalEnums.GameClasses> { }
public HashSetClassType classAllowed = new HashSetClassType();

public int inventoryIndex;
public GameObject socket;

}

ItemslotEditor.cs

[CustomEditor(typeof(Itemslot))]
public class ItemslotEditor : Editor
{


public override void OnInspectorGUI()
{        
    serializedObject.Update();
    Itemslot component = (Itemslot)target;

    GUILayout.BeginVertical("box");

    EditorGUILayout.PropertyField(serializedObject.FindProperty("socket"));
    EditorGUILayout.PropertyField(serializedObject.FindProperty("inventoryIndex"));

    var style = new GUIStyle(GUI.skin.button);
    int counter = 0;


    EditorGUILayout.LabelField("Allowed Types");

    GUILayout.BeginHorizontal();

    foreach (GlobalEnums.ItemType t in Enum.GetValues(typeof(GlobalEnums.ItemType)))
    {
        if (counter % 3 == 0 && counter > 1)
        {
            GUILayout.EndHorizontal();
            GUILayout.BeginHorizontal();
        }

        if (component.typeAllowed.Contains(t))
        {
            GUI.backgroundColor = Color.green;
        }
        else
        {
            GUI.backgroundColor = Color.white;
        }

        if (GUILayout.Button(t.ToString(), style, GUILayout.Width(120), GUILayout.Height(30)))
        {
            if (component.typeAllowed.Contains(t))
            {
                component.typeAllowed.Remove(t);
            }
            else
            {
                component.typeAllowed.Add(t);
            }
        }

        counter++;

    }

    GUILayout.EndHorizontal();
    GUILayout.BeginHorizontal();

    GUI.backgroundColor = Color.red;
    if (GUILayout.Button("NONE", style, GUILayout.Width(150), GUILayout.Height(25)))
    {
        component.typeAllowed.Clear();
    }

    GUI.backgroundColor = Color.yellow;
    if (GUILayout.Button("ALL", style, GUILayout.Width(150), GUILayout.Height(25)))
    {
        foreach (GlobalEnums.ItemType t in Enum.GetValues(typeof(GlobalEnums.ItemType)))
        {
            component.typeAllowed.Add(t);
        }
    }

    GUILayout.EndHorizontal();

    EditorGUILayout.LabelField("Allowed Classes");
    counter = 0;

    GUILayout.BeginHorizontal();

    foreach (GlobalEnums.GameClasses t in Enum.GetValues(typeof(GlobalEnums.GameClasses)))
    {
        if (counter % 3 == 0 && counter > 1)
        {
            GUILayout.EndHorizontal();
            GUILayout.BeginHorizontal();
        }

        if (component.classAllowed.Contains(t))
        {
            GUI.backgroundColor = Color.green;
        }
        else
        {
            GUI.backgroundColor = Color.white;
        }

        if (GUILayout.Button(t.ToString(), style, GUILayout.Width(120), GUILayout.Height(30)))
        {
            if (component.classAllowed.Contains(t))
            {
                component.classAllowed.Remove(t);
            }
            else
            {
                component.classAllowed.Add(t);
            }
        }

        counter++;

    }

    GUILayout.EndHorizontal();
    GUILayout.BeginHorizontal();

    GUI.backgroundColor = Color.red;
    if (GUILayout.Button("NONE", style, GUILayout.Width(150), GUILayout.Height(25)))
    {
        component.classAllowed.Clear();
    }

    GUI.backgroundColor = Color.yellow;
    if (GUILayout.Button("ALL", style, GUILayout.Width(150), GUILayout.Height(25)))
    {
        foreach (GlobalEnums.GameClasses t in Enum.GetValues(typeof(GlobalEnums.GameClasses)))
        {
            component.classAllowed.Add(t);
        }
    }

    GUILayout.EndHorizontal();
    GUILayout.EndVertical();

    serializedObject.ApplyModifiedProperties();

}

}

最佳答案

Unity 无法序列化 HashSet<T> ,因此您的更改永远不会保存到磁盘。

这里有两个选择:

编辑

以下是如何使用 ISerializationCallbackReceiver 执行此操作的示例界面。

public class Itemslot : MonoBehaviour, IDropHandler, IPointerEnterHandler, 
IPointerExitHandler, ISerializationCallbackReceiver
{
    public HashSet<GlobalEnums.ItemType> typeAllowed = new HashSet<GlobalEnums.ItemType>();

    // private field to ensure serialization
    [SerializeField]
    private List<GlobalEnums.ItemType> _typeAllowedList = new List<GlobalEnums.ItemType>();

    public void OnBeforeSerialize()
    {
        // store HashSet contents in List
        _typeAllowedList.Clear();
        foreach(var allowedType in typeAllowed)
        {
            _typeAllowedList.Add(allowedType);
        }
    }

    public void OnAfterDeserialize()
    {
        // load contents from the List into the HashSet
        typeAllowed.Clear();
        foreach(var allowedType in _typeAllowedList)
        {
            typeAllowed.Add(allowedType);
        }
    }
}

关于c# - Unity 中 HashSet 的自定义检查器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46676915/

相关文章:

ios - 从 Unity iOS 项目创建 pod

c# - 如何通过套接字从 UWP 应用程序连接到 Unity 游戏服务器套接字?

java - eclipse 删除逗号的按键绑定(bind)

c# - 添加控件以从ViewModel查看

c# - 数学解释为什么 Decimal 到 Double 的转换被破坏并且 Decimal.GetHashCode 分隔相等的实例

c# - 如何返回 C# 中最大元素的数组?

c# - 一次显式输入所有变量

c# - MySql 数据库上的目录隐私会阻止 C# 吗?

jquery - GWT/GXT 标签编辑器?

java - Eclipse编辑器问题: It only shows one element instead of whole source code!