「Unity3D」(12)EditorWindow使用Scrip

作者: 飞机王 | 来源:发表于2018-06-04 15:14 被阅读38次

    通常绘制EditorWindow需要手动一个个手动绘制控件和布局,但是联想到Inspector可以根据SerializedObject对象自动绘制和布局,那么如果我们可以根据SerializedObject对象来控制EditorWindow的显示,然后在此之上再进行一些自定义工作,岂不是会方便快捷很多。

    本文将会介绍,如何使用ScriptableObject对象的Inspector绘制,来填充EditorWindow的界面显示。关于Inspector绘制介绍见这篇文章:自定义属性面板Inspector详解

    ScriptableObject对象的Inpsector绘制

    ScriptableObject对象可以运行时存储临时数据,也可以生成.asse文件持久化数据,如果ScriptableObject持久化对象对应一个EditorWindow窗口,刚好可以当做窗口配置数据源来使用。当然,ScriptableObject的asset文件本身拥有Inpsector编辑显示能力,可以单独用来保存数据使用。比如,建立如下一个ScriptableObject子类:

    using UnityEngine;
    using System.Collections;
    
    // 生成入口到Unity菜单Assets->Create下
    [CreateAssetMenu(menuName = "Create ShowObject")]
    public class ShowObject : ScriptableObject
    {
        public Vector3 position;
        [Space(20)] // 注意,ShowObject需要单独一个文件,并且文件名与类名一致,[]属性才能有效。
        public string  label;
        [Range(0, 10)] // 注意,ShowObject需要单独一个文件,并且文件名与类名一致,[]属性才能有效。
        public int     intData;
        public bool    isCheck;
        public Options options;
        public Shader  defaultShader;
    
        public enum Options
        {
            Opt1,
            Opt2,
            Opt3,
        }
    }
    

    这样,我们就能够创建一个ShowObject的asset文件,而选中这个asset文件,就可以看到ShowObject的绘制和布局。我们就是需要把这个Inspector的显示,放入到EditorWindow之中绘制。

    创建EditorWindow

    public class EditorWindows : EditorWindow
    {
        [MenuItem("ExtendingEditor/ShowObject Window")]
        public static void ShowObjectWindow() 
        {
            EditorWindow.GetWindow<EditorWindows>(true, "ShowObject Window", true);
        }
    
        private void OnGUI() 
        {
            // 绘制ScriptableObject的Inspector显示,目前是空的。
        }
    }
    

    绘制ScriptableObject

    有两种方法,来绘制ScriptableObject的内容:

    • 手动遍历ScriptableObject每个属性绘制。
    • 自动调用ScriptableObject Inspector的绘制方法。

    第一种,手动遍历ScriptableObject

    首先,我们需要创建ScriptableObject对象,然后构建一个SerializedObject,接着遍历绘制SerializedObject的每一个Property。

    public class EditorWindows : EditorWindow
    {
        private SerializedObject serializedObject;
    
        [MenuItem("ExtendingEditor/ShowObject Window")]
        public static void ShowObjectWindow() 
        {
            var window = EditorWindow.GetWindow<EditorWindows>(true, "ShowObject Window", true);
            // 创建ScriptableObject并生成SerializedObject
            window.serializedObject = new SerializedObject(ScriptableObject.CreateInstance<ShowObject>());
        }
    
        private void OnGUI() 
        {
            this.serializedObject.Update();
            
            var iterator = this.serializedObject.GetIterator();
            // go to child
            iterator.NextVisible(true);
            // skip name
            iterator.Next(false);
            // skip EditorClassIdentifier
            iterator.Next(false);
            
            // 遍历每一个属性并绘制
            while (iterator.Next(false))
            {
                EditorGUILayout.PropertyField(iterator);
            }
        
            this.serializedObject.ApplyModifiedProperties();
        }
    }
    

    第二种,调用ScriptableObject Inspector的绘制

    既然ScriptableObject有自己的Inspector绘制,那么我们就可以直接调用Inspector的Editor绘制,而不需要自己手动遍历SerializedObject的属性。

    public class EditorWindows : EditorWindow
    {
        private Editor editor;
    
        [MenuItem("ExtendingEditor/ShowObject Window")]
        public static void ShowObjectWindow() 
        {
            var window = EditorWindow.GetWindow<EditorWindows>(true, "ShowObject Window", true);
            // 直接根据ScriptableObject构造一个Editor
            window.editor = Editor.CreateEditor(ScriptableObject.CreateInstance<ShowObject>());
        }
    
        private void OnGUI() 
        {
            // 直接调用Inspector的绘制显示
            this.editor.OnInspectorGUI();
        }
    }
    

    效果

    更多设想

    既然ScriptableObject有自己的Inspector的Editor绘制,那么我们就可以自定义扩展它,然后就可以直接显示在EditorWindows里面了。比如:

    // 自定义ScriptableObject的Editor显示
    [CanEditMultipleObjects, CustomEditor(typeof(ShowObject))]
    public class ShowObjectEditor : Editor
    {
    }
    

    当然,也可以使用PropertyDrawer和PropertyAttribute来进行扩展。


    「简化自定义窗口工作」

    相关文章

      网友评论

        本文标题:「Unity3D」(12)EditorWindow使用Scrip

        本文链接:https://www.haomeiwen.com/subject/egfysftx.html