|
今天无意间发现了一篇好文章,也让我解决了一个很久都没解决的难题。问题是这样的,假如我想去拓展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()方式以后,原有的布局都就变了
为什么会影响到原有布局呢?原因是这样的上面的代码是担任Editor的,那么base.OnInspectorGUI()实际上去掉用了Editor类里的OnInspectorGUI()方式,可是RectTransfm的OnInspectorGUI()方式是在RectTransformEditor这个类写的。
但是问题就来了,RectTransformEditor这个类不是一个对外公开的类。所以不能担任它,那也就无法调用它的OnInspectorGUI()方式了,所以就有了上述问题。
这里有一个巧妙的反射方式,完美的解决这个问题。Extend Unity's built-in inspectors (GitHub: Where the world builds software)
理论上unity提供的每一个脚本都有一个 XXXEditor 类 , 用来绘制它的面板。(本文用到的就是 RectTransformEditor)如果你不确定可以去我反编译的代码里面去找。xuanyusong / unity-decompiled — Bitbucket
如下图所示,此刻既保留了原有的布局,也可以便利的拓展了。。
- 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)
注:此方式有个短处,不撑持多选操作,多选时候写的面板会消掉。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|