今天无意间发现了一篇好文章,也让我解决了一个很久都没解决的难题。问题是这样的,假如我想去拓展Unity自带的inspector但是并不想影响原有布局。 比如下面这段代码:

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
[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()方法了,所以就有了上述问题。

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

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
[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

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

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
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的更多相关文章

  1. Unity3D研究院编辑器之Editor的GUI的事件拦截

    OnGUI是Unity上一个时代的UI系统,而现在运行时的UI系统已经被UGUI取代,但是Editor的UI还是在用老的这一套GUI系统.比如unity编辑器里的所有窗口,布局,按钮,拖动条.滚动等等 ...

  2. Unity3D研究院编辑器之脚本设置ToolBar

    Unity版本5.3.2 如下图所示,ToolBar就是Unity顶部的那一横条.这里的所有按钮一般情况下都得我们手动的用鼠标去点击.这篇文章我们说说如果自动操作它们 1.自动点击左边四个按钮 (拖动 ...

  3. Unity3D研究院编辑器之脚本设置ToolBar及脚本设置顶视图

    Unity版本5.3.2 如下图所示,ToolBar就是Unity顶部的那一横条.这里的所有按钮一般情况下都得我们手动的用鼠标去点击.这篇文章我们说说如果自动操作它们 1.自动点击左边四个按钮 (拖动 ...

  4. [Unity] Unity3D研究院编辑器之自定义默认资源的Inspector面板

    比如编辑模式下对场景或者特定文件夹有一些操作可以在这个面板里来完成.. 代码如下. using UnityEngine; using System.Collections; using UnityEd ...

  5. [Unity] Unity3D研究院编辑器之独立Inspector属性

    本文转自: http://www.xuanyusong.com/archives/3680雨松MOMO Unity提供了强大的Editor功能, 我们可以很轻易的在EditorGUI中绘制任意的属性. ...

  6. Unity3D研究院编辑器之不实例化Prefab获取删除更新组件(十五)

    http://www.xuanyusong.com/archives/3727 感谢楼下的牛逼回复更正一下,我表示我也是才知道.. 其实不需要实例化也能查找,你依然直接用GetComponentsIn ...

  7. Unity3D研究院编辑器之脚本获取资源内存和硬盘大小

    内存 使用Profiler可以查看某个资源的内存占用情况,但是必须启动游戏,并且待查看的资源已经载入游戏中.我希望的是不启动游戏,也能看到它的内存好做统计. 硬盘 由于unity中的资源压缩格式记录在 ...

  8. Unity3D研究院编辑器之重写Hierarchy的右键菜单

    Hierarchy视图中选择一个游戏对象以后通过右键可以打开一个unity默认菜单,一般情况下都可以满足我们,但是我想真对某些特殊的游戏对象而展开特殊的菜单.如下图所示,比如这样: 代码: using ...

  9. Unity3D研究院编辑器之自定义默认资源的Inspector面板

    比如编辑模式下对场景或者特定文件夹有一些操作可以在这个面板里来完成. 代码如下: using System.Collections; using System.Collections.Generic; ...

随机推荐

  1. HDU 3829 - Cat VS Dog (二分图最大独立集)

    题意:动物园有n只猫和m条狗,现在有p个小孩,他们有的喜欢猫,有的喜欢狗,其中喜欢猫的一定不喜欢狗,喜欢狗的一定不喜欢猫.现在管理员要从动物园中移除一些动物,如果一个小孩喜欢的动物留了下来而不喜欢的动 ...

  2. BZOJ 1568 Blue Mary开公司

    李超线段树. GTMD调了一下午... #include<iostream> #include<cstdio> #include<cstring> #include ...

  3. BZOJ 4027 兔子与樱花

    原来想的是给所有点排序....但是要修改啊...然后发现对于儿子排序就可以了. #include<iostream> #include<cstdio> #include< ...

  4. BZOJ 1968 约数研究

    其实打个表就会发现,这个玩意儿是积性的,然后很happy的搞了一下. 不,不是这样. 考虑每个约数对答案的贡献,不难发现:约数i的贡献为n/i. 加之即可. #include<iostream& ...

  5. 【Android UI】 Shape详解

    在Android开发过程中,经常需要改变控件的默认样式, 那么通常会使用多个图片来解决.不过这种方式可能需要多个图片,比如一个按钮,需要点击时的式样图片,默认的式样图片. 这样就容易使apk变大. 那 ...

  6. C++之创建对象时的new与不new

    C++在创建对象的时候可以采用两种方式:(例如类名为Test) Test test  或者 Test* pTest = new Test(). 这两种方法都可以实例化一个对象,但是这两种方法有很大的区 ...

  7. mysql联合索引详解

    联合索引又叫复合索引.对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索 引中的一部份,但只能是最左侧部分.例如索引是key index (a,b,c). 可以支持a | a,b ...

  8. SQL备份还原,分离附加

    备份.还原.分离.附加 备份:在要备份的数据库上右键点击任务,在选择备份.在打卡的对话框中根据需要选择.注意:备份过期时间不能为0,否则会马上过期.目标可根据需要放在任何位置.最后,点击确定,备份成功 ...

  9. [转]MMORPG服务器架构

    MMORPG服务器架构 一.摘要 1.网络游戏MMORPG整体服务器框架,包括早期,中期,当前的一些主流架构2.网络游戏网络层,包括网络协议,IO模型,网络框架,消息编码等.3.网络游戏的场景管理,A ...

  10. hadoop权威指南 读书笔记

    1 数据库和MapReduce对比 2 hadoop 包含的内容