unity3d Unity Simple Property Drawer或弹出窗口,用于显示自定义对象-数组可编写脚本的对象

lb3vh1jj  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(188)

我对Unity和C#还很陌生,我尝试复制一个看似简单的自定义编辑器和属性抽屉,用于我通过脚本对象准备的数据。在本例中,一个类在gameObject上使用多个标签,当很多东西被传感器检测到时,我很快就能识别出什么是什么。我已经用了太久了,我怀疑我的理智,因为这不可能那么难。我“我想我只是缺乏一些基本的知识/理解。关于SerializedProperty的整个概念和对它的处理对我来说非常不直观。
在这里找到了这个方便的代码片段,用于创建包含多个层的LayerMasks:

using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(SingleUnityLayer))]
public class SingleUnityLayerPropertyDrawer : PropertyDrawer
{
    public override void OnGUI(Rect _position, SerializedProperty _property, GUIContent _label)
    {
        EditorGUI.BeginProperty(_position, GUIContent.none, _property);
        SerializedProperty layerIndex = _property.FindPropertyRelative("m_LayerIndex");
        _position = EditorGUI.PrefixLabel(_position, GUIUtility.GetControlID(FocusType.Passive), _label);
        if (layerIndex != null)
        {
            layerIndex.intValue = EditorGUI.LayerField(_position, layerIndex.intValue);
        }
        EditorGUI.EndProperty();
    }
}

它在这个类中工作

using UnityEngine;

[System.Serializable]
public class SingleUnityLayer {
    [SerializeField]
    private int m_LayerIndex = 0;
    private string m_LayerName = "";

    public int LayerIndex {
        get { return m_LayerIndex; }
    }

    public string LayerName {
        get { return m_LayerName; }
    }

    public void Set(int _layerIndex) {
        if(_layerIndex > 0 && _layerIndex < 32) {
            m_LayerIndex = _layerIndex;
            m_LayerName = LayerMask.LayerToName(m_LayerIndex);
        }
    }

    public int Mask {
        get { return 1 << m_LayerIndex; }
    }
}

并创造了这个结果,这是伟大的:
enter image description here

**现在:**我想做同样的事情,显示一个自定义标记的数组,脚本化对象类,或者如果需要,甚至是一个简单的字符串[],但不能使它工作。抽屉的属性字段将类似于public Tag[] tags;,其中Tag类暂时只包含一个公共名称属性。

我甚至没有我的许多尝试的代码,因为它变得混乱,我有点放弃了,我找到了一些解决方案,我甚至没有尝试,因为他们似乎方式复杂,是必要的,简单的任务.
有人能把我推向正确的方向吗?比“阅读自定义编辑器”多一点就太棒了;)
谢谢
(not真的在这里的主题,但如果有人能告诉我一个更好的(便宜)的方式来识别碰撞检测与重叠圈比与标签,请告诉;)
(hope代码块和东西的工作..第一篇文章)

**编辑:**在@derHugo的帮助下,我想出了一个简单的解决方案,他比我自己更了解我想要什么:

[CustomPropertyDrawer(typeof(SingleUnityTag))]
public class SingleUnityTagPropertyDrawer : PropertyDrawer {
    //string selectedTag = "";
    public override void OnGUI(Rect _position, SerializedProperty _property, GUIContent _label) {
        EditorGUI.BeginProperty(_position, GUIContent.none, _property);
        SerializedProperty tagIndex = _property.FindPropertyRelative("m_TagIndex");
        SerializedProperty tagName = _property.FindPropertyRelative("m_TagName");
        _position = EditorGUI.PrefixLabel(_position, GUIUtility.GetControlID(FocusType.Passive), _label);
        if(tagIndex != null) {
            tagName.stringValue = EditorGUI.TagField(_position, tagName.stringValue);
        }
        EditorGUI.EndProperty();
    }
}
hc2pp10m

hc2pp10m1#

因此,如果我理解正确的话,现在你实际上想要的不是一个ScriptableObject,而是一个自定义标签选择下拉列表。
不幸的是,没有内置的东西,但你可以创建一个使用EditorGUI.TagField,如。

using System;
    using UnityEngine;
#if UNITY_EDITOR
    using System.Linq;
    using UnityEditor;
#endif

    public class TagAttribute : PropertyAttribute
    {
#if UNITY_EDITOR
        [CustomPropertyDrawer(typeof(TagAttribute))]
        private class TagAttributeDrawer : PropertyDrawer
        {
            public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
            {
                return EditorGUIUtility.singleLineHeight;
            }

            public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
            {
                EditorGUI.BeginProperty(position, label, property);

                if (property.propertyType != SerializedPropertyType.String)
                {
                    EditorGUI.HelpBox(position, $"{nameof(TagAttribute)} can only be used for strings!", MessageType.Error);
                    return;
                }

                if (!UnityEditorInternal.InternalEditorUtility.tags.Contains(property.stringValue))
                {
                    property.stringValue = "";
                }

                var color = GUI.color;
                if (string.IsNullOrWhiteSpace(property.stringValue))
                {
                    GUI.color = Color.red;
                }

                property.stringValue = EditorGUI.TagField(position, label, property.stringValue);
                GUI.color = color;

                EditorGUI.EndProperty();
            }
        }
#endif
    }

因此在您的组件中,现在只需

[Tag] public string tag;

[Tag] public string[] tags;

相关问题