unity3d 统一编辑器:System.ArgumentException:重新绘制时获取控件1在仅有1个控件的组中的位置

5sxhfpxr  于 2023-03-19  发布在  其他
关注(0)|答案(1)|浏览(172)

我正在尝试实现显示通过属性添加到ObjectField的对象的属性。通过自定义编辑器,我可以,但我厌倦了为每个新类创建一个编辑器。我想通过属性。
属性代码:

[System.AttributeUsage(System.AttributeTargets.Field)]
public class DisplayPropertiesAttribute : PropertyAttribute
{
    public DisplayPropertiesAttribute() { }
}

出票人代码:

[CustomPropertyDrawer(typeof(DisplayPropertiesAttribute))]
    public class DisplayPropertiesDrawer : PropertyDrawer
    {
        private Editor editor;
        private bool foldout;

        /// <summary>
        /// Overrides GUI drawing for the attribute
        /// </summary>
        /// <param name="position"><see cref="Rect"/> fields to activate validation</param>
        /// <param name="property">Serializedproperty the object</param>
        /// <param name="label">Displaу field label</param>
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {// Check if this is reference type property
            if (property.propertyType != SerializedPropertyType.ObjectReference)
            {
                // If field is not reference, show error message.            
                var style = new GUIStyle(EditorStyles.objectField);
                style.normal.textColor = Color.red;

                // Display label with error message
                EditorGUI.LabelField(position, label, new GUIContent($"{property.propertyType} is not a reference type"), style);
                return;
            }

            // If there is already an editor, add a foldout icon
            if (editor) { foldout = EditorGUI.Foldout(position, foldout, new GUIContent()); }

            // Start blocking change checks
            EditorGUI.BeginChangeCheck();
            // Display a ObjectField
            EditorGUI.ObjectField(position, property, label);
            // If changes were made to the contents of the field,
            // or the reference is empty, there is an editor,
            // or the reference is there but there is no editor
            if (EditorGUI.EndChangeCheck() || (property.objectReferenceValue ^ editor))
            {
                // Create an editor for the object pointed to by the reference, even if reference is empty
                editor = Editor.CreateEditor(property.objectReferenceValue);
            }

            // If foldout is true and the Editor exists
            if (foldout && editor)
            {
                // Draw the properties of an object in a frame
                GUILayout.BeginVertical(EditorStyles.helpBox);
                editor.OnInspectorGUI();
                GUILayout.EndVertical();
            }
        }
    }

滚动时(字段隐藏在屏幕框架后面),出现错误:System.ArgumentException: Getting control 1's position in a group with only 1 controls when doing repaint不显示属性。而是显示空白...
显示数组仍然有一个问题,但现在我想至少摆脱这个错误。
我将错误封装在try-catch中,只是隐藏了属性,但看起来很糟糕。

// Draw the properties of an object in a frame
                try
                {
                    GUILayout.BeginVertical(EditorStyles.helpBox);
                    editor.OnInspectorGUI();
                    GUILayout.EndVertical();
                }
                catch (System.ArgumentException e)
                {
                    foldout = false;
                }
wn9m85ua

wn9m85ua1#

您的问题是,在PropertyDrawer中,您无法使用来自GUILayoutEditorGUILayout的自动布局API,而只能使用来自GUIEditorGUI的绝对Rect API,始终传入相应的起始位置和尺寸。
你需要

  • 计算显示嵌套内容所需的总高度
  • 将此高度添加到public override float GetPropertyHeight,它将告诉检查员根据Rect保留绘制您的属性
  • 将相应的为子编辑器保留的Rect传递到editor中,并在给定位置和尺寸处绘制

=〉您不能简单地使用默认编辑器来实现这一点,因为它在自动布局系统中运行,而PropertyDrawers无法使用该系统。

相关问题