如何使Vector3字段的行为类似于CustomEditor中Transform中的字段

时间:2019-02-21 18:39:01

标签: unity3d custom-controls unity3d-editor unity-editor

在以下gif中,您可以看到Vector3和我的Transform的检查器中MonoBehaviour字段的行为方式。

enter image description here

Transform甚至是我也使用CustomEditor写的EditorGUILayout.Vector3Field()

[CustomEditor(typeof(Transform), true)]
[CanEditMultipleObjects]
public class AdvancedTransformEditor : Editor
{
    //Unity's built-in editor
    private Editor _defaultEditor;
    private Transform _transform;

    private void OnEnable()
    {
        //When this inspector is created, also create the built-in inspector
        _defaultEditor = CreateEditor(targets, Type.GetType("UnityEditor.TransformInspector, UnityEditor"));
        _transform = target as Transform;
    }

    private void OnDisable()
    {
        //When OnDisable is called, the default editor we created should be destroyed to avoid memory leakage.
        //Also, make sure to call any required methods like OnDisable
        var disableMethod = _defaultEditor.GetType().GetMethod("OnDisable", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
        if (disableMethod != null) disableMethod.Invoke(_defaultEditor, null);
        DestroyImmediate(_defaultEditor);
    }

    public override void OnInspectorGUI()
    {
        EditorGUILayout.LabelField("Local Space", EditorStyles.boldLabel);
        _defaultEditor.OnInspectorGUI();

        serializedObject.Update();

        //Show World Space Transform
        EditorGUILayout.Space();
        EditorGUILayout.LabelField("World Space", EditorStyles.boldLabel);

        _transform.position = EditorGUILayout.Vector3Field("Position", _transform.position);

        EditorGUI.BeginDisabledGroup(true);
        EditorGUILayout.Vector3Field("Rotation", _transform.eulerAngles);
        EditorGUILayout.Vector3Field("Scale", _transform.lossyScale);
        EditorGUI.EndDisabledGroup();

        serializedObject.ApplyModifiedProperties();
    }
}

它只有在拥有_defaultEditor.OnInspectorGUI();的情况下才能工作,因此Unity的Transform组件的原始编辑器中的某些功能必须有所不同。

当我尝试在其他CustomEditor中为MonoBehaviour做同样的事情

// without a CustomEditor
public class Example : MonoBehaviour
{
    public Vector3 example;
}

// Width the custom editor
public class ExampleMinWidth : MonoBehaviour
{
    public Vector3 example;
}

[CustomEditor(typeof(ExampleMinWidth))]
public class ExampleMinWidthEditor : Editor
{
    private SerializedProperty example;

    private void OnEnable()
    {
        example = serializedObject.FindProperty("exmaple");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        example.vector3Value = EditorGUILayout.Vector3Field("Example", example.vector3Value);

        // I tried both also simply using a PropertyField
        //EditorGUILayout.PropertyField(example);
        serializedObject.ApplyModifiedProperties();
    }
}

或跳过_defaultEditor.OnInspectorGUI();中的行AdvancedTransformEditorVector3字段将折叠为特定的Inspector宽度。

如何为我的字段获得与Transform组件相同的行为-不折叠而是保持在同一行?


更新

  • 我用GUILayout.MinWidth()进行了尝试,但这没有任何改变。

  • 根据建议,我也尝试过

    example.vector3Value = EditorGUILayout.Vector3Field("Example", example.vector3Value, GUILayout.ExpandHeight(false));
    

    (也适用于PropertyField()),但没有任何改变。

  • 而且我也尝试使用ExpandWidth(false) ... ...结果不是很令人满意:D

    enter image description here

  • 我什至尝试过GUILayout.MaxHeight(EditorGUIUtility.singleLineHeight),但这会使字段仍然折叠,但会在下面的字段中“重载” /透支。

3 个答案:

答案 0 :(得分:1)

EditorGUILayout.Vector3Field带有可选的第三个参数(GUILayoutOption的数组),您可以在其中指定类似的内容。您需要传递以下内容:GUILayout.ExpandHeight(false)

答案 1 :(得分:1)

Unity3d在GitHub上有其source code,您可以在其中看到Transform组件的实现。

TransformInspector.cs:

/ Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License

using UnityEngine;

namespace UnityEditor
{
    [CustomEditor(typeof(Transform))]
    [CanEditMultipleObjects]
    internal class TransformInspector : Editor
    {
        SerializedProperty m_Position;
        SerializedProperty m_Scale;
        TransformRotationGUI m_RotationGUI;

        class Contents
        {
            public GUIContent positionContent = EditorGUIUtility.TrTextContent("Position", "The local position of this GameObject relative to the parent.");
            public GUIContent scaleContent = EditorGUIUtility.TrTextContent("Scale", "The local scaling of this GameObject relative to the parent.");
            public string floatingPointWarning = LocalizationDatabase.GetLocalizedString("Due to floating-point precision limitations, it is recommended to bring the world coordinates of the GameObject within a smaller range.");
        }
        static Contents s_Contents;

        public void OnEnable()
        {
            m_Position = serializedObject.FindProperty("m_LocalPosition");
            m_Scale = serializedObject.FindProperty("m_LocalScale");

            if (m_RotationGUI == null)
                m_RotationGUI = new TransformRotationGUI();
            m_RotationGUI.OnEnable(serializedObject.FindProperty("m_LocalRotation"), EditorGUIUtility.TrTextContent("Rotation", "The local rotation of this GameObject relative to the parent."));
        }

        public override void OnInspectorGUI()
        {
            if (s_Contents == null)
                s_Contents = new Contents();

            if (!EditorGUIUtility.wideMode)
            {
                EditorGUIUtility.wideMode = true;
                EditorGUIUtility.labelWidth = EditorGUIUtility.currentViewWidth - 212;
            }

            serializedObject.Update();

            Inspector3D();
            // Warning if global position is too large for floating point errors.
            // SanitizeBounds function doesn't even support values beyond 100000
            Transform t = target as Transform;
            Vector3 pos = t.position;
            if (Mathf.Abs(pos.x) > 100000 || Mathf.Abs(pos.y) > 100000 || Mathf.Abs(pos.z) > 100000)
                EditorGUILayout.HelpBox(s_Contents.floatingPointWarning, MessageType.Warning);

            serializedObject.ApplyModifiedProperties();
        }

        private void Inspector3D()
        {
            EditorGUILayout.PropertyField(m_Position, s_Contents.positionContent);
            m_RotationGUI.RotationField();
            EditorGUILayout.PropertyField(m_Scale, s_Contents.scaleContent);
        }
    }
}

答案 2 :(得分:1)

我在TransformInspector

中找到了相关的行
ScrollView
  • EditorGUIUtility.wideMode做两件事:返回当前编辑器是否处于宽屏模式,设置是否用于此组件/下一行的行为应与在宽模式下相同。因此,他们只是强制其字段仅在宽屏模式下“存在”。

  • 此后,有必要使用“固定” EditorGUIUtility.labelWidth,即减小宽度的3 if (!EditorGUIUtility.wideMode) { EditorGUIUtility.wideMode = true; EditorGUIUtility.labelWidth = EditorGUIUtility.currentViewWidth - 212; } 字段将采用宽模式(Unity使用212)