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

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

[复制链接]
发表于 2024-7-15 17:55 | 显示全部楼层 |阅读模式
今天无意间发现了一篇好文章,也让我解决了一个很久都没解决的难题。问题是这样的,假如我想去拓展Unity自带的inspector但是并不想影响原有布局。 比如下面这段代码:
  1. [CustomEditor(typeof(RectTransform))]
  2. public class MyTest : Editor
  3. {
  4.     public override void OnInspectorGUI ()
  5.     {
  6.         base.OnInspectorGUI ();
  7.         if(GUILayout.Button(”Adding this button”))
  8.         {
  9.             Debug.Log(”Adding this button”);
  10.         }
  11.     }
  12. }
复制代码
我的本意是想在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
如下图所示,此刻既保留了原有的布局,也可以便利的拓展了。。

  1. using System.Collections.Generic;
  2. using System.Linq;
  3. using System.Reflection;
  4. using UnityEditor;
  5. using UnityEngine;
  6. /// <summary>
  7. /// A base class for creating editors that decorate Unity&#39;s built-in editor types.
  8. /// </summary>
  9. public abstract class DecoratorEditor : Editor
  10. {
  11.     // empty array for invoking methods using reflection
  12.     private static readonly object[] EMPTY_ARRAY = new object[0];
  13.    
  14.     #region Editor Fields
  15.    
  16.     /// <summary>
  17.     /// Type object for the internally used (decorated) editor.
  18.     /// </summary>
  19.     private System.Type decoratedEditorType;
  20.    
  21.     /// <summary>
  22.     /// Type object for the object that is edited by this editor.
  23.     /// </summary>
  24.     private System.Type editedObjectType;
  25.    
  26.     private Editor editorInstance;
  27.    
  28.     #endregion
  29.     private static Dictionary<string, MethodInfo> decoratedMethods = new Dictionary<string, MethodInfo>();
  30.    
  31.     private static Assembly editorAssembly = Assembly.GetAssembly(typeof(Editor));
  32.    
  33.     protected Editor EditorInstance
  34.     {
  35.         get
  36.         {
  37.             if (editorInstance == null && targets != null && targets.Length > 0)
  38.             {
  39.                 editorInstance = Editor.CreateEditor(targets, decoratedEditorType);
  40.             }
  41.             
  42.             if (editorInstance == null)
  43.             {
  44.                 Debug.LogError(”Could not create editor !”);
  45.             }
  46.             
  47.             return editorInstance;
  48.         }
  49.     }
  50.    
  51.     public DecoratorEditor (string editorTypeName)
  52.     {
  53.         this.decoratedEditorType = editorAssembly.GetTypes().Where(t => t.Name == editorTypeName).FirstOrDefault();
  54.         
  55.         Init ();
  56.         
  57.         // Check CustomEditor types.
  58.         var originalEditedType = GetCustomEditorType(decoratedEditorType);
  59.         
  60.         if (originalEditedType != editedObjectType)
  61.         {
  62.             throw new System.ArgumentException(
  63.                 string.Format(”Type {0} does not match the editor {1} type {2}”,
  64.                           editedObjectType, editorTypeName, originalEditedType));
  65.         }
  66.     }
  67.    
  68.     private System.Type GetCustomEditorType(System.Type type)
  69.     {
  70.         var flags = BindingFlags.NonPublic  | BindingFlags.Instance;
  71.         
  72.         var attributes = type.GetCustomAttributes(typeof(CustomEditor), true) as CustomEditor[];
  73.         var field = attributes.Select(editor => editor.GetType().GetField(”m_InspectedType”, flags)).First();
  74.         
  75.         return field.GetValue(attributes[0]) as System.Type;
  76.     }
  77.    
  78.     private void Init()
  79.     {      
  80.         var flags = BindingFlags.NonPublic  | BindingFlags.Instance;
  81.         
  82.         var attributes = this.GetType().GetCustomAttributes(typeof(CustomEditor), true) as CustomEditor[];
  83.         var field = attributes.Select(editor => editor.GetType().GetField(”m_InspectedType”, flags)).First();
  84.         
  85.         editedObjectType = field.GetValue(attributes[0]) as System.Type;
  86.     }
  87.     void OnDisable()
  88.     {
  89.         if (editorInstance != null)
  90.         {
  91.             DestroyImmediate(editorInstance);
  92.         }
  93.     }
  94.    
  95.     /// <summary>
  96.     /// Delegates a method call with the given name to the decorated editor instance.
  97.     /// </summary>
  98.     protected void CallInspectorMethod(string methodName)
  99.     {
  100.         MethodInfo method = null;
  101.         
  102.         // Add MethodInfo to cache
  103.         if (!decoratedMethods.ContainsKey(methodName))
  104.         {
  105.             var flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public;
  106.             
  107.             method = decoratedEditorType.GetMethod(methodName, flags);
  108.             
  109.             if (method != null)
  110.             {
  111.                 decoratedMethods[methodName] = method;
  112.             }
  113.             else
  114.             {
  115.                 Debug.LogError(string.Format(”Could not find method {0}”, method));
  116.             }
  117.         }
  118.         else
  119.         {
  120.             method = decoratedMethods[methodName];
  121.         }
  122.         
  123.         if (method != null)
  124.         {
  125.             method.Invoke(EditorInstance, EMPTY_ARRAY);
  126.         }
  127.     }
  128.     public void OnSceneGUI()
  129.     {
  130.         CallInspectorMethod(”OnSceneGUI”);
  131.     }
  132.     protected override void OnHeaderGUI ()
  133.     {
  134.         CallInspectorMethod(”OnHeaderGUI”);
  135.     }
  136.    
  137.     public override void OnInspectorGUI ()
  138.     {
  139.         EditorInstance.OnInspectorGUI();
  140.     }
  141.    
  142.     public override void DrawPreview (Rect previewArea)
  143.     {
  144.         EditorInstance.DrawPreview (previewArea);
  145.     }
  146.    
  147.     public override string GetInfoString ()
  148.     {
  149.         return EditorInstance.GetInfoString ();
  150.     }
  151.    
  152.     public override GUIContent GetPreviewTitle ()
  153.     {
  154.         return EditorInstance.GetPreviewTitle();
  155.     }
  156.    
  157.     public override bool HasPreviewGUI ()
  158.     {
  159.         return EditorInstance.HasPreviewGUI ();
  160.     }
  161.    
  162.     public override void OnInteractivePreviewGUI (Rect r, GUIStyle background)
  163.     {
  164.         EditorInstance.OnInteractivePreviewGUI (r, background);
  165.     }
  166.    
  167.     public override void OnPreviewGUI (Rect r, GUIStyle background)
  168.     {
  169.         EditorInstance.OnPreviewGUI (r, background);
  170.     }
  171.    
  172.     public override void OnPreviewSettings ()
  173.     {
  174.         EditorInstance.OnPreviewSettings ();
  175.     }
  176.    
  177.     public override void ReloadPreviewInstances ()
  178.     {
  179.         EditorInstance.ReloadPreviewInstances ();
  180.     }
  181.    
  182.     public override Texture2D RenderStaticPreview (string assetPath, Object[] subAssets, int width, int height)
  183.     {
  184.         return EditorInstance.RenderStaticPreview (assetPath, subAssets, width, height);
  185.     }
  186.    
  187.     public override bool RequiresConstantRepaint ()
  188.     {
  189.         return EditorInstance.RequiresConstantRepaint ();
  190.     }
  191.    
  192.     public override bool UseDefaultMargins ()
  193.     {
  194.         return EditorInstance.UseDefaultMargins ();
  195.     }
  196. }
复制代码
版本: Unity5.3.3
转载链接:Unity3D研究院编纂器之不影响原有布局拓展Inspector(二十四) | 雨松MOMO法式研究院 (xuanyusong.com)
注:此方式有个短处,不撑持多选操作,多选时候写的面板会消掉。

本帖子中包含更多资源

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

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

本版积分规则

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

GMT+8, 2024-11-21 20:26 , Processed in 0.146067 second(s), 28 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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