找回密码
 立即注册
查看: 444|回复: 0

Unity编辑器不影响原有布局拓展Inspector(转载)

[复制链接]
发表于 2022-3-26 21:06 | 显示全部楼层 |阅读模式
今天无意间发现了一篇好文章,也让我解决了一个很久都没解决的难题。问题是这样的,假如我想去拓展Unity自带的inspector但是并不想影响原有布局。 比如下面这段代码:
[CustomEditor(typeof(RectTransform))]public class MyTest : Editor {    public override void OnInspectorGUI ()    {        base.OnInspectorGUI ();        if(GUILayout.Button("Adding this button"))        {            Debug.Log("Adding this button");        }    } }
我的本意是想在Rect Transform面板的下面去添加一个按钮,可是我一旦调用base.OnInspectorGUI()方法以后,原有的布局都就变了


image.png

为什么会影响到原有布局呢?原因是这样的上面的代码是继承Editor的,那么base.OnInspectorGUI()实际上去掉用了Editor类里的OnInspectorGUI()方法,可是RectTransfm的OnInspectorGUI()方法是在RectTransformEditor这个类写的。

但是问题就来了,RectTransformEditor这个类不是一个对外公开的类。所以不能继承它,那也就无法调用它的OnInspectorGUI()方法了,所以就有了上述问题。

这里有一个巧妙的反射方法,完美的解决这个问题。Extend Unity's built-in inspectors (github.com)
[CustomEditor(typeof(RectTransform))]public class MyTest : DecoratorEditor{    public MyTest(): base("RectTransformEditor"){}    public override void OnInspectorGUI ()    {        base.OnInspectorGUI ();        if(GUILayout.Button("Adding this button"))        {            Debug.Log("Adding this button");        }    }}
理论上unity提供的每一个脚本都有一个 XXXEditor 类 , 用来绘制它的面板。(本文用到的就是 RectTransformEditor)如果你不确定可以去我反编译的代码里面去找。xuanyusong / unity-decompiled — Bitbucket

如下图所示,现在既保留了原有的布局,也可以方便的拓展了。。


image.png

using System.Collections.Generic;using System.Linq;using System.Reflection;using UnityEditor;using UnityEngine; /// <summary>/// A base class for creating editors that decorate Unity's built-in editor types./// </summary>public abstract class DecoratorEditor : Editor{    // empty array for invoking methods using reflection    private static readonly object[] EMPTY_ARRAY = new object[0];        #region Editor Fields        /// <summary>    /// Type object for the internally used (decorated) editor.    /// </summary>    private System.Type decoratedEditorType;        /// <summary>    /// Type object for the object that is edited by this editor.    /// </summary>    private System.Type editedObjectType;        private Editor editorInstance;        #endregion     private static Dictionary<string, MethodInfo> decoratedMethods = new Dictionary<string, MethodInfo>();        private static Assembly editorAssembly = Assembly.GetAssembly(typeof(Editor));        protected Editor EditorInstance    {        get        {            if (editorInstance == null && targets != null && targets.Length > 0)            {                editorInstance = Editor.CreateEditor(targets, decoratedEditorType);            }                        if (editorInstance == null)            {                Debug.LogError("Could not create editor !");            }                        return editorInstance;        }    }        public DecoratorEditor (string editorTypeName)    {        this.decoratedEditorType = editorAssembly.GetTypes().Where(t => t.Name == editorTypeName).FirstOrDefault();                Init ();                // Check CustomEditor types.        var originalEditedType = GetCustomEditorType(decoratedEditorType);                if (originalEditedType != editedObjectType)        {            throw new System.ArgumentException(                string.Format("Type {0} does not match the editor {1} type {2}",                           editedObjectType, editorTypeName, originalEditedType));        }    }        private System.Type GetCustomEditorType(System.Type type)    {        var flags = BindingFlags.NonPublic  | BindingFlags.Instance;                var attributes = type.GetCustomAttributes(typeof(CustomEditor), true) as CustomEditor[];        var field = attributes.Select(editor => editor.GetType().GetField("m_InspectedType", flags)).First();                return field.GetValue(attributes[0]) as System.Type;    }        private void Init()    {               var flags = BindingFlags.NonPublic  | BindingFlags.Instance;                var attributes = this.GetType().GetCustomAttributes(typeof(CustomEditor), true) as CustomEditor[];        var field = attributes.Select(editor => editor.GetType().GetField("m_InspectedType", flags)).First();                editedObjectType = field.GetValue(attributes[0]) as System.Type;    }     void OnDisable()    {        if (editorInstance != null)        {            DestroyImmediate(editorInstance);        }    }        /// <summary>    /// Delegates a method call with the given name to the decorated editor instance.    /// </summary>    protected void CallInspectorMethod(string methodName)    {        MethodInfo method = null;                // Add MethodInfo to cache        if (!decoratedMethods.ContainsKey(methodName))        {            var flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public;                        method = decoratedEditorType.GetMethod(methodName, flags);                        if (method != null)            {                decoratedMethods[methodName] = method;            }            else            {                Debug.LogError(string.Format("Could not find method {0}", method));            }        }        else        {            method = decoratedMethods[methodName];        }                if (method != null)        {            method.Invoke(EditorInstance, EMPTY_ARRAY);        }    }     public void OnSceneGUI()    {        CallInspectorMethod("OnSceneGUI");    }     protected override void OnHeaderGUI ()    {        CallInspectorMethod("OnHeaderGUI");    }        public override void OnInspectorGUI ()    {        EditorInstance.OnInspectorGUI();    }        public override void DrawPreview (Rect previewArea)    {        EditorInstance.DrawPreview (previewArea);    }        public override string GetInfoString ()    {        return EditorInstance.GetInfoString ();    }        public override GUIContent GetPreviewTitle ()    {        return EditorInstance.GetPreviewTitle();    }        public override bool HasPreviewGUI ()    {        return EditorInstance.HasPreviewGUI ();    }        public override void OnInteractivePreviewGUI (Rect r, GUIStyle background)    {        EditorInstance.OnInteractivePreviewGUI (r, background);    }        public override void OnPreviewGUI (Rect r, GUIStyle background)    {        EditorInstance.OnPreviewGUI (r, background);    }        public override void OnPreviewSettings ()    {        EditorInstance.OnPreviewSettings ();    }        public override void ReloadPreviewInstances ()    {        EditorInstance.ReloadPreviewInstances ();    }        public override Texture2D RenderStaticPreview (string assetPath, Object[] subAssets, int width, int height)    {        return EditorInstance.RenderStaticPreview (assetPath, subAssets, width, height);    }        public override bool RequiresConstantRepaint ()    {        return EditorInstance.RequiresConstantRepaint ();    }        public override bool UseDefaultMargins ()    {        return EditorInstance.UseDefaultMargins ();    }}
版本: Unity5.3.3

转载链接:Unity3D研究院编辑器之不影响原有布局拓展Inspector(二十四) | 雨松MOMO程序研究院 (xuanyusong.com)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-22 15:48 , Processed in 0.090276 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表