第三章自定义检视面板_创建自定义编辑器类_编扩展默认组件的显示面板(本章进度6/9)

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 ,会自动设置锚点,如下图

相关推荐
山峰哥5 天前
吃透 SQL 优化:告别慢查询,解锁数据库高性能
服务器·数据库·sql·oracle·性能优化·编辑器
holeer6 天前
【V1.0】Typora 中的 HTML 支持|软件文档自翻译
前端·编辑器·html·typora·web·markdown·文档
硬汉嵌入式6 天前
Vim 9.2版本正式发布
编辑器·vim
吹牛不交税6 天前
关于vscode左侧资源管理器目录层级疑似异常的问题
ide·vscode·编辑器
No8g攻城狮6 天前
【Linux】Linux nano 编辑器全攻略:从入门到精通
linux·运维·编辑器·nano
你怎么知道我是队长6 天前
VsCode插件推荐---Todo Tree
ide·vscode·编辑器
becatjd6 天前
VScode的claude code插件报错command ‘claude-vscode.editor.openLast‘ not found
ide·vscode·编辑器·claude·anthropic·claude code
BIBI20496 天前
下载指定历史版本 VSCode 或 VSCode Insider
ide·vscode·编辑器
johnny2337 天前
编辑器和笔记软件汇总:Typst、Reminds、Memos、Editor、MDX Notes、Jotty
笔记·编辑器
宫瑾7 天前
vscode未定义标识符报错的解决方法
ide·vscode·编辑器