通过Editor类中的CreateEditor方法可以实现在不改变原有编辑器布局的情况下进行拓展,下面以Rect Transform组件的编辑器为例:
如图所示,我们在不改变RectTransform原有编辑器布局的情况下,添加了一个Auto Anchors功能,该功能方便我们在搭建UI时自动设置锚点。
原有的编辑器布局通过CreateEditor方法来创建一个编辑器类,在OnInspectorGUI中调用其OnInspectorGUI方法即可,同时需要在OnSceneGUI中调用其OnSceneGUI方法:
代码语言:javascript复制using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Reflection;
namespace SK.Framework
{
[CustomEditor(typeof(RectTransform)), CanEditMultipleObjects]
public sealed class RectTransformInspector : Editor
{
private Editor instance;
private MethodInfo onSceneGUI;
private static readonly object[] emptyArray = new object[0];
private void OnEnable()
{
//获取编辑器类型
var editorType = Assembly.GetAssembly(typeof(Editor)).GetTypes().FirstOrDefault(m => m.Name == "RectTransformEditor");
//创建编辑器类实例
instance = CreateEditor(targets, editorType);
//通过反射获取OnSceneGUI方法
onSceneGUI = editorType.GetMethod("OnSceneGUI", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
}
public override void OnInspectorGUI()
{
if (instance)
{
instance.OnInspectorGUI();
}
}
private void OnSceneGUI()
{
if(instance)
{
onSceneGUI.Invoke(instance, emptyArray);
}
}
private void OnDisable()
{
if(instance)
{
DestroyImmediate(instance);
}
}
}
}
下面添加拓展功能Auto Anchors,首先我们希望可以多选进行编辑,因此注意需要添加Can Edit Multiple Objects属性,然后在OnInspectorGUI中进行代码添加即可:
代码语言:javascript复制public override void OnInspectorGUI()
{
if (instance)
{
instance.OnInspectorGUI();
}
GUILayout.Space(20f);
if (GUILayout.Button("Auto Anchors"))
{
//遍历所有选中的RectTransform
for (int i = 0; i < targets.Length; i )
{
RectTransform tempTarget = targets[i] as RectTransform;
Undo.RecordObject(tempTarget, "Auto Anchors");
RectTransform prt = tempTarget.parent as RectTransform;
Vector2 anchorMin = new Vector2(
tempTarget.anchorMin.x tempTarget.offsetMin.x / prt.rect.width,
tempTarget.anchorMin.y tempTarget.offsetMin.y / prt.rect.height);
Vector2 anchorMax = new Vector2(
tempTarget.anchorMax.x tempTarget.offsetMax.x / prt.rect.width,
tempTarget.anchorMax.y tempTarget.offsetMax.y / prt.rect.height);
tempTarget.anchorMin = anchorMin;
tempTarget.anchorMax = anchorMax;
tempTarget.offsetMin = tempTarget.offsetMax = Vector2.zero;
}
}
}
锚点自动设置完成:
完整代码:
代码语言:javascript复制using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Reflection;
namespace SK.Framework
{
[CustomEditor(typeof(RectTransform)), CanEditMultipleObjects]
public sealed class RectTransformInspector : Editor
{
private MethodInfo onSceneGUI;
private Editor instance;
private static readonly object[] emptyArray = new object[0];
private void OnEnable()
{
var editorType = Assembly.GetAssembly(typeof(Editor)).GetTypes().FirstOrDefault(m => m.Name == "RectTransformEditor");
instance = CreateEditor(targets, editorType);
onSceneGUI = editorType.GetMethod("OnSceneGUI", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
}
public override void OnInspectorGUI()
{
if (instance)
{
instance.OnInspectorGUI();
}
GUILayout.Space(20f);
if(GUILayout.Button("Auto Anchors"))
{
for (int i = 0; i < targets.Length; i )
{
RectTransform tempTarget = targets[i] as RectTransform;
Undo.RecordObject(tempTarget, "Auto Anchors");
RectTransform prt = tempTarget.parent as RectTransform;
Vector2 anchorMin = new Vector2(
tempTarget.anchorMin.x tempTarget.offsetMin.x / prt.rect.width,
tempTarget.anchorMin.y tempTarget.offsetMin.y / prt.rect.height);
Vector2 anchorMax = new Vector2(
tempTarget.anchorMax.x tempTarget.offsetMax.x / prt.rect.width,
tempTarget.anchorMax.y tempTarget.offsetMax.y / prt.rect.height);
tempTarget.anchorMin = anchorMin;
tempTarget.anchorMax = anchorMax;
tempTarget.offsetMin = tempTarget.offsetMax = Vector2.zero;
}
}
}
private void OnSceneGUI()
{
if(instance)
{
onSceneGUI.Invoke(instance, emptyArray);
}
}
private void OnDisable()
{
if(instance)
{
DestroyImmediate(instance);
}
}
}
}