unity3d 扩展unity原有的Inspector

unity3d 扩展unity原有的Inspector_第1张图片

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

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

这里有一个巧妙的反射方法,完美的解决这个问题。https://gist.github.com/liortal53/352fda2D01d339306e03

[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)如果你不确定可以去我反编译的代码里面去找。https://bitbucket.org/xuanyusong/unity-decompiled


using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
  
/// 
/// A base class for creating editors that decorate Unity's built-in editor types.
/// 
public abstract class DecoratorEditor : Editor
{
    // empty array for invoking methods using reflection
    private static readonly object[] EMPTY_ARRAY = new object[0];
     
    #region Editor Fields
     
    /// 
    /// Type object for the internally used (decorated) editor.
    /// 
    private System.Type decoratedEditorType;
     
    /// 
    /// Type object for the object that is edited by this editor.
    /// 
    private System.Type editedObjectType;
     
    private Editor editorInstance;
     
    #endregion
  
    private static Dictionary decoratedMethods = new Dictionary();
     
    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);
        }
    }
     
    /// 
    /// Delegates a method call with the given name to the decorated editor instance.
    /// 
    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小技巧)