3.1.5 扩展默认组件的显示面板
为Unity 的 RectTransform 组件添加了一个一键锚点自动设置工具,在保留 Unity 内置编辑器所有功能的基础上,增加了实用功能。
csharp
// 引入必要的命名空间
using System;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
/// <summary>
/// 声明自定义编辑器,作用于RectTransform组件
/// 一键自动计算并设置锚点
//保持 UI 元素在父容器中的相对位置
//自动重置偏移量为零
/// </summary>
[CustomEditor(typeof(RectTransform))]
public class RectTransformEditorExample : Editor
{
private RectTransform rt; // 当前编辑的RectTransform组件
private Editor instance; // 内置RectTransform编辑器的实例
private MethodInfo onSceneGUI; // 内置编辑器的OnSceneGUI方法引用
private static readonly object[] emptyArray = new object[0]; // 空参数数组用于反射调用
// 初始化方法
private void OnEnable()
{
rt = target as RectTransform;
if (rt == null)
return;
// 反射获取Unity内置的RectTransformEditor类型
var editorType = Assembly.GetAssembly(typeof(Editor)) // 获取Editor所在程序集
.GetTypes() // 获取程序集中所有类型
.FirstOrDefault( // 查找符合条件的第一个类型
m => m.Name == "RectTransformEditor" // 根据名称匹配内置编辑器
);
// 创建内置编辑器实例
instance = CreateEditor(targets, editorType);
// 反射获取内置编辑器的私有OnSceneGUI方法
onSceneGUI = editorType.GetMethod(
"OnSceneGUI",
BindingFlags.Instance | BindingFlags.NonPublic); //
}
// 场景视图绘制
private void OnSceneGUI()
{
// 调用内置编辑器的场景视图绘制方法
onSceneGUI?.Invoke(instance, emptyArray);
}
// 清理资源
private void OnDisable()
{
if (instance != null)
{
DestroyImmediate(instance); // 销毁内置编辑器实例
}
}
// 绘制Inspector面板
public override void OnInspectorGUI()
{
// 先绘制默认的Inspector内容
instance.OnInspectorGUI();
// 添加自定义的锚点工具
OnAnchorSetHelperGUI();
}
// 自定义的锚点工具GUI
private void OnAnchorSetHelperGUI()
{
EditorGUILayout.Space();
// 使用醒目颜色标题
Color color = GUI.color;
GUI.color = Color.cyan;
GUILayout.Label("锚点工具", EditorStyles.boldLabel);
GUI.color = color;
// Auto Anchor按钮
if (GUILayout.Button("Auto Anchor"))
{
// 注册撤销操作
Undo.RecordObject(rt, "Auto Anchor");
// 获取父物体的RectTransform
RectTransform prt = rt.parent as RectTransform;
if (prt == null)
return;
// 核心算法:计算新的锚点位置
Vector2 anchorMin = new(
rt.anchorMin.x + rt.offsetMin.x / prt.rect.width,
rt.anchorMin.y + rt.offsetMin.y / prt.rect.height
);
Vector2 anchorMax = new(
rt.anchorMax.x + rt.offsetMax.x / prt.rect.width,
rt.anchorMax.y + rt.offsetMax.y / prt.rect.height
);
// 应用新锚点并重置偏移量
rt.anchorMin = anchorMin;
rt.anchorMax = anchorMax;
rt.offsetMin = Vector2.zero;
rt.offsetMax = Vector2.zero;
}
}
}
效果是这样的,当我们移动UI控件时,锚点是不会跟着移动的,需要我们用预设好的锚点位置,或者手动调整,一下比较麻烦一些,如下图。
点击Auto Anchor ,会自动设置锚点,如下图
