Unity简单属性抽屉或弹出显示自定义对象数组可脚本对象



我对unity和c#仍然很陌生,并试图复制一个看似简单的自定义编辑器和属性抽屉,用于我通过可脚本对象准备的数据。在这种情况下,类在游戏对象上使用多个标签,以便在传感器检测到大量标签时快速识别哪些是什么。我这么做太久了,一直在质疑我的理智,因为这不会太难。我想我只是缺乏一些相当基本的知识/理解。对我来说,SerializedProperty的整个概念和它的处理是非常不直观的。

在这里找到这个方便的代码片段来创建包含多个图层的layermask:

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

并创建了这个结果,这很好:

输入图片描述

:我想有同样的事情,显示一个自定义标记可脚本对象类的数组,甚至一个简单的字符串[],如果有必要,但不能让它工作。抽屉的属性字段类似于public Tag[] tags;,其中Tag类目前只包含一个公共名称属性。

我甚至没有我多次尝试的代码,因为它变得混乱,我有点放弃了,我在网上找到了一些解决方案,我甚至没有尝试,因为他们似乎太复杂了,对于那个简单的任务是必要的。

谁能给我指个对的方向?比"阅读自定义编辑器"多一点;太棒了;)

感谢(这里不是真正的主题,但如果有人能告诉我一个更好(便宜)的方法来识别碰撞检测与重叠圈比标签,请告诉;)

(希望代码块和东西工作…第一个帖子)

编辑:在@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();
}
}

所以如果我理解正确的话,现在你真正想要的不是一个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;

最新更新