Unity编辑器拓展最全实现

news2025/8/9 17:04:59

1编辑器顶部菜单学习

 验证事项

2编辑器Scene菜单学习 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestSceneMenu : MonoBehaviour
{  

    [InitializeOnLoadMethod]   //加入这个属性,就相当于在编辑器启动的时候执行
    static void Ind() {
        UnityEditor.SceneView.duringSceneGui += (u) =>
        {
            //在Scene窗口绘制菜单,只需要在DuringSceneGui绑入一个事件即可

            if (Event.current != null &&Event.current.button == 1 && Event.current.type == EventType.MouseUp){
                //if里面是描述鼠标右键事件按下,

                Rect position = new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y-100,100,100);
                //描绘菜单的Rect方框的位置

                GUIContent[] contens = new GUIContent[] { new GUIContent("Test1"),new GUIContent("先锋/Test2")};
                //菜单里面的按钮数组
                EditorUtility.DisplayCustomMenu(position, contens,-1,(data, opt, select)=> {
                    Debug.LogFormat("data:{0},opt:{1},select:{2},value:{3}",data,opt,select,opt[select]);
                },null);

                //这是描绘菜单按钮所需要传入的属性,(位置,按钮数组,是否选择(传入按钮数组没有的下标代表不选择),每个按钮所需要处理的点击回调,一般传入空值即可)

                Event.current.Use();   //将鼠标复原到指针icon
            }
        };
    }
    
}

3编辑器如何给按钮添加快捷键学习

4Assets菜单栏拓展

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestProject : MonoBehaviour
{



    [MenuItem("Assets/Test1")]
    static void Test1()
    {
        Debug.Log("Assets  Test1");
        //Project文件夹下的按钮,直接把路径改成Assects即可
    }


    /// <summary>
    /// 在资源右侧加上按钮
    /// </summary>
    [InitializeOnLoadMethod]
    static void InitializeOnLoad()
    {

        //这个是在Project的窗口创建按钮   guid是Assects下所有资源的唯一标识符   
        //rect每个资源所占的选中方框大小,
        EditorApplication.projectWindowItemOnGUI += (guid, rect) =>
        {

            //是否选中资源
            if (Selection.activeObject != null)
            {

                //获取资源的GUID唯一标识符
                string Select_guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(Selection.activeObject));
                //判断传入的唯一标识符和点击的唯一标识符是否一致
                if (guid == Select_guid&&!string.IsNullOrEmpty (Select_guid))
                {
                    //按照所占方框去创建按钮大小
                    rect.x = rect.width - 100;
                    rect.width = 100;
                    if (GUI.Button(rect, "delect"))
                    {
                        //删除资源方法
                        AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(Selection.activeObject));
                        Debug.LogFormat("资源唯一标识符:{0}", Select_guid);
                    }

                }

            }

        };
    }
}

 5Project事件介绍

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestProjectEvent : UnityEditor.AssetModificationProcessor
{
    /// <summary>
    /// 将要创建资源的会执行的方法
    /// </summary>
    /// <param name="Path"></param>
    public static void OnWillCreateAsset(string Path)
    {
        Debug.LogFormat("创建资源{0}", Path);
    }

    /// <summary>
    /// 点击Apply保存资源所执行的方法
    /// </summary>
    /// <param name="paths"></param>
    /// <returns></returns>
    public static string[] OnWillSaveAssets(string[] paths)
    {

        for (int i = 0; i < paths.Length; i++)
        {
            Debug.LogFormat("保存的资源{0}", paths[i]);
        }
        return paths;
    }


    /// <summary>
    /// 移动资源所执行的方法
    /// </summary>
    /// <param name="OldPath"></param>
    /// <param name="NewPath"></param>
    /// <returns></returns>
    public static AssetMoveResult OnWillMoveAsset(string OldPath, string NewPath)
    {

        Debug.LogFormat("移动资源从{0}到{1}", OldPath, NewPath);
        ///需要返回枚举
        return AssetMoveResult.DidNotMove;   //允许移动
        //return AssetMoveResult.DidMove;    //不允许移动
        //return AssetMoveResult.FailedMove;   //不允许移动

    }


    /// <summary>
    /// 删除资源所执行的方法    删除资源的路径,操作的枚举,枚举中表述的是删除之后是否进入回收站
    /// </summary>
    /// <param name="path"></param>
    /// <param name="opt"></param>
    /// <returns></returns>
    public static AssetDeleteResult OnWillDeleteAsset(string path, RemoveAssetOptions opt)
    {


        Debug.LogFormat("删除资源:{0}  options:{1}", path, opt);



        return AssetDeleteResult.DidNotDelete;  //可以删除
        //return AssetDeleteResult.DidDelete;   //不能删除
        //return AssetDeleteResult.FailedDelete;   //不能删除
    }


    /// <summary>
    /// 这个标头是项目初始化,监听资源发生变化
    /// </summary>
    [InitializeOnLoadMethod]
    static void InitOnLoad()
    {

        ///根据不同回调监听不同界面的资源回调
        EditorApplication.projectChanged += () =>
        {
            Debug.Log("资源发生改变");
        };

        EditorApplication.hierarchyChanged+=()=> {
            Debug.Log("层级资源发生改变");
        };
    }


}

6层级面板的拓展

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestHierarchy : MonoBehaviour
{

    /// <summary>
    /// 层级面板右键按钮拓展
    /// </summary>
    [MenuItem("GameObject/Test2", false, 0)]
    public static void Test2()
    {
        Debug.Log("GameObject  Test2");
        
    }

    /// <summary>
    /// 在层级资源右侧加上按钮
    /// </summary>
    [InitializeOnLoadMethod]
    static void InitializeOnLoad()
    {

        //这个是在Hierarchy的资源左侧创建按钮   InstancesID是Hierarchy下所有资源的唯一ID  
        //rect每个资源所占的选中方框大小,
        EditorApplication.hierarchyWindowItemOnGUI += (InstancesID, rect) =>
        {
            //是否选中资源   判断选择的资源id和传入的ID是否相等
            if (Selection.activeObject != null&&InstancesID==Selection.activeObject.GetInstanceID())
            {                               
                    //按照所占方框去创建按钮大小
                    rect.x = rect.width - 50;
                    rect.width = 100;
                    if (GUI.Button(rect, "delect"))
                    {
                    //删除资源方法
                    GameObject.DestroyImmediate(Selection.activeObject);
                        Debug.LogFormat("删除资源:{0}", InstancesID);
                    }              
            }

        };
    }


}

7抛弃原来的菜单,重新创建菜单

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestMenuOverride
{

    [InitializeOnLoadMethod]
    static void InitOnLoad() {
        ///监听鼠标在层级面板窗口
        EditorApplication.hierarchyWindowItemOnGUI += (InstanceID, rect) =>
        {
            if (Event.current != null)
            {
                ///判断右键抬起
                if (Event.current.button == 1 && Event.current.type == EventType.MouseUp)
                {
                    //阻断本身的右键菜单展出
                    //Event.current.Use();

                    //创建自己的菜单按钮,可以看到本身自己的菜单,在”先锋“的地方传入自己的菜单名称即可
                    //EditorUtility.DisplayPopupMenu(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 100, 100)
                      //  ,"先锋",null);

                    Debug.Log("鼠标抬起");                    
                }
            }

        };
    }

}

8在Inspector面板组件拓展 (在代码或者组件下面加按钮)

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

/// <summary>
/// CustomEditor属性指定类型,下面就是在Camera组件加入按钮
/// </summary>
[CustomEditor(typeof(Camera))]
public class TestInspector : Editor
{

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();  //保持原生的组件属性  

        ///加入按钮,并且监听按钮按下
        if (GUILayout.Button("Test1")){
            Debug.Log("雨一直下,气氛不算融化ikun");

            ///获取目标组件
            Camera c = this.target as Camera;
            if (c != null) {
                c.fieldOfView = 10;
            }
        }

    }

}

9在Inspector Context组件拓展(组件右键面板加按钮)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestInspectorContext : MonoBehaviour
{

    /// <summary>
    /// 命名规则   CONTEXT/组件名字(代码名字)/按钮名字)
    /// </summary>
    /// <param name="command"></param>
    [MenuItem("CONTEXT/Transform/Test1")]
    static void SetPosition(MenuCommand command) {

        Transform transform = command.context as Transform;

        if (transform != null) {
            transform.position = Vector3.zero;
            Debug.Log("重置位置");
        }
    }
    


}

10Scene视图拓展(Gizmos画图)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestScene : MonoBehaviour
{

#if UNITY_EDITOR

    public  Color color;

    /// <summary>
    /// 选中才绘制
    /// </summary>
    private void OnDrawGizmosSelected()
    {
        Gizmos.DrawLine(transform .position,transform .position +Vector3 .up);
        Gizmos.color = color;
        Gizmos.DrawSphere(transform.position ,1);
    }

    /// <summary>
    /// 一直绘制
    /// </summary>
    private void OnDrawGizmos()
    {
        //Gizmos.DrawLine(transform.position, transform.position + Vector3.up);
        //Gizmos.color = color;
        //Gizmos.DrawSphere(transform.position, 1);


    }
#endif

}

11在Scene视图加UI

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(TestScene))]
public class TestSceneGUI : Editor
{
    private void OnSceneGUI()
    {
        Handles.BeginGUI();    //3d中开始2D块
        if (GUILayout.Button("TestScene",GUILayout.Width (100))) {
            Debug.Log("This TestScene");
        }

        Handles.EndGUI();
    }
}

12在Scene视图加固定的UI

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(TestScene))]
public class TestSceneGUI : Editor
{
    private void OnSceneGUI()
    {
        Handles.BeginGUI();    //3d中开始2D块
        if (GUILayout.Button("TestScene",GUILayout.Width (100))) {
            Debug.Log("This TestScene");
        }

        Handles.EndGUI();
    }



    [InitializeOnLoadMethod]
    static void InitLoad() {
        //代码启动就开始画UI
        SceneView.duringSceneGui += (sceneView) =>
        {
            Handles.BeginGUI();    //3d中开始2D块
            //按钮
            if (GUILayout.Button("Test2", GUILayout.Width(100)))
            {
                Debug.Log("This TestScene");
            }
            //标签
            GUILayout.Label("先锋");

            Handles.EndGUI();
        };
    }
}

13Game视图增加拓展

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 这个特性运行在编辑器下,不需要运行就能出现按钮,如果
/// 不加属性,需要运行才会出现在Game视图(需要将代码挂载到物体上)
/// </summary>
[ExecuteInEditMode]
public class TestGame : MonoBehaviour
{
    private void OnGUI()
    {
        if (GUILayout.Button("Test1",GUILayout.Width(100))) {
            Debug.Log("Test Scene");
        }
    }
}

14在编辑器下创建自己的窗口

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestWindow : EditorWindow
{
    /// <summary>
    /// 在窗口中创建一个按钮
    /// </summary>
    private void OnGUI()
    {
        if (GUILayout.Button("创建对象")) {
            Debug.Log("创建模型");
        }
    }


    //以下都是生命周期

    /// <summary>
    /// 窗口启动
    /// </summary>
    private void Awake()
    {
        Debug.Log("Awake");
    }

    /// <summary>
    /// 窗口销毁
    /// </summary>
    private void OnDestroy()
    {
        Debug.Log("OnDestroy");
    }

    /// <summary>
    /// 鼠标焦点,当鼠标出去再进来会执行一次
    /// </summary>
    private void OnFocus()
    {
        Debug.Log("OnFocus");
    }


    /// <summary>
    /// 窗口常输出
    /// </summary>
    private void Update()
    {
        Debug.Log("Update");
    }
}

创建一个按钮打开窗口

15窗口中右上角下拉菜单的拓展

效果图

 

 16 在自己创建的Window窗口创建模型预览窗口

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestPreview : EditorWindow
{

    Object Obj;   //
    Editor PreviewObj;

    Object LatsObj;

    /// <summary>
    /// 创建一个文件输入窗口
    /// </summary>
    private void OnGUI()
    {
        //可以在这里点击输出框
        Obj=EditorGUILayout.ObjectField(Obj,typeof(Object),false);

        //创建一个窗口
        if (Obj!=null&&Obj!= LatsObj) {
            PreviewObj = Editor.CreateEditor(Obj);
            LatsObj = Obj;
        }

        //创建预览画面
        if (PreviewObj != null) {
            PreviewObj.OnPreviewGUI(GUILayoutUtility.GetRect(400, 400), EditorStyles.label);
        }
        

    }


    /// <summary>
    /// 打开预览窗口
    /// </summary>
    [MenuItem("先锋/预览窗口")]
    static void Test3() {
        TestPreview tp = EditorWindow.GetWindow<TestPreview>();
        tp.Show();
    }

}

 效果实现

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/34047.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

7.前端笔记-CSS-元素显示模式

HTML元素分为块元素和行内元素两种类型 1、块元素 常见的块元素&#xff1a; <h1>~<h6> <p> <div> <ul> <ol> <li>块元素的特点&#xff1a; &#xff08;1&#xff09;独占一行 &#xff08;2&#xff09;高度、宽度、内外边距可…

java线程池详解

一 介绍 线程我们可以使用 new 的方式去创建&#xff0c;但如果并发的线程很多&#xff0c;每个线程执行的时间又不长&#xff0c;这样频繁的创建线程会大大的降低系统处理的效率&#xff0c;因为创建和销毁进程都需要消耗资源&#xff0c;线程池就是用来解决类似问题。 线程…

餐饮+KTV融合消费模式,会受消费者喜欢吗?

这个五一&#xff0c;我们雨科网门店系统的客户&#xff0c;大侠火锅店终于是将KTV搬到了自己的门店里&#xff0c;运用门店小程序功能及纸质代金券及礼品的噱头吸引客户进店&#xff0c;只需消费并和任意一人合唱一首歌即可领取&#xff0c;消费者在等餐或放松的时候一键点歌演…

一起来了解下 TOWER “未知装置”

从 2022 年 11 月 9 日开始&#xff0c;TOWER 未知装置可在 TOWER Token 网站&#xff08;https://www.crazydefenseheroes.com/fusion/game-assets&#xff09;上使用&#xff0c;允许玩家使用 TOWER Token 融合他们的 NFT 或将他们现有的 TOWER NFT 跟踪为不同的形式。 第一阶…

js - js中关于getBoundingClientRect()方法的使用

介绍一下getBoundingClientRect()方法的一些属性&#xff0c;以及具体的使用场景和一些需要注意的问题&#xff1b; 1&#xff0c;介绍 此方法返回元素的大小及其相对于视口的位置&#xff1b;返回的是一个对象&#xff1a; 包括 left、top、right、bottom、x、y、width 和 he…

ThinkPHP5目录结构

文章目录一、TP5的框架的下载1、[采用fastAdmin安装](https://www.fastadmin.net/download.html)2、Composer安装2.1 Composer提供的服务3、Git安装二、使用Composer安装后目录结构2.1 补充获取 Git 仓库git的工作机制一、TP5的框架的下载 1、采用fastAdmin安装 FastAdmin是一…

数据可视化大屏设计

在数据业务展示场景中&#xff0c;数据可视化大屏已经变得十分常见。那么在设计思路上&#xff0c;数据可视化大屏应当遵循什么样的设计逻辑&#xff1f;本篇文章里做了介绍&#xff0c;一起来看一下。 一、数据大屏的应用场景 1、大型会议 2、业务展示 二、数据大屏分类 1、展…

阿里云新用户滑块验证不过,阿里云滑动验证流程及线上问题排查

滑动验证是阿里巴巴集团提供的一种验证码解决方案&#xff0c;采用风险分析引擎&#xff0c;有效区分来自人类与机器人的访问行为并拦截机器风险&#xff0c;为您提供安全可靠的业务环境。 下图是滑动验证在用户客户端的展示效果。 产品介绍&#xff1a;阿里云验证码&#x…

5.XMLHttpRequest对象

XMLHttpRequest简称xhr&#xff0c;是浏览器提供的Javascript对象。之前我们使用的都是jQuery中的Ajax&#xff0c;现在我们使用原生JS的Ajax 目录 1 GET请求 1.1 不带参数请求 1.2 带参数请求 2 URL的编码与解码 2.1 编码 encodeURI() 2.2 解码 decodeURI() 3 …

计算机网络——TCP连接管理

本文将会介绍如何建立和拆除一条TCP连接&#xff0c;TCP的连接会显著的增加人们感受到的时延&#xff08;尤其是在Web冲浪时&#xff09;。同时一些常见的网络攻击SYN洪范攻击利用了TCP连接管理的弱点。 假定运行一台主机&#xff08;客户&#xff09;上的一个进程想和另一台主…

Spring中各种注解的使用说明汇总清单

目录 一、放在最开始方法的外侧的注解 1、ControllerAdvice&#xff1a; 2、ResponseBody 3、slf4j 4、Configuration 5、Component 6、Mapper 7、Service 8、RestController RequestMapping("/路径") 9、EnableTransactionManagement和Transactional&…

maven学习:maven安装、maven仓库、Idea配置maven

一、maven安装 1.1 下载maven Maven的版本对应的jdk和发布日期:Maven – Maven Releases History 到官方网站下载maven,网站: Maven – Download Apache Maven 如下图: 下载maven之前的版本:Index of /dist/maven/maven-3 注意&#xff1a; idea与maven的版本需要兼容, 所以我…

Python学的好,工作不愁找

俗话说的好&#xff1a;“Python学的好&#xff0c;工作不愁找”&#xff0c;不管我们学习哪一门语言&#xff0c;我们都要掌握从抽象化中提取出来的方法&#xff0c;这样你才能提高我们的学习能力&#xff0c;并且在学习新事物的时候可以提取我们自己的想法。学习Python&#…

基于SpringBoot的仿小米商城系统

仿小米商城分为前后台&#xff0c;分为用户和管理员两种角色&#xff0c;管理员可以登录后台管理系统~ 可以作为毕设~也可以作为学习的项目~ 前台部分运行截图如下所示 后台部分运行截图如下所示 拒绝白嫖&#xff01;20分享源码&#xff01;want to get it 私 me&#xf…

Java入门简单小游戏有哪些?

适合新手练习的小游戏有超级玛丽、愤怒的小鸟、飞机大战、五子棋、彩虹雨、聊天室、华容道、坦克大战、扫雷等。还有贪吃蛇&#xff0c;由Java开发出来的一款经典小游戏&#xff0c;java小白入门可以用这款游戏开发练手锻炼自己的编程能力。 教程推荐&#xff1a;玩会Java&…

【Linux】(六)MobaXterm文件传输与终端-实验室服务器使用MobaXterm传输文件和ssh终端连接

MobaXterm系列文章文件传输或远程终端&#xff08;MobaXterm&#xff09;系列文章 &#xff08;一&#xff09;服务器初次配置及安装vncserver &#xff08;二&#xff09;实验室添加新用户及其配置vnc4server、xfce4桌面访问流程 &#xff08;三&#xff09;VNC桌面连接开发方…

C++初阶(stack+queue)

stack是一种容器适配器&#xff0c;专门用在具有后进先出 (last-in first-out)操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入与提取操作。stack是作为容器适配器被实现的&#xff0c;容器适配器即是对特定类封装作为其底层的容器&#xff0c;并提供一组…

Unity RectTransform 组件

文章目录1.RectTransform 介绍2.Anchor 锚点3.Pivot 轴心点4.RectTransform API 属性4.1 anchorMax、anchorMin —— 锚点矩形4.2 offsetMax、offsetMin —— 偏移量4.3 rect —— 矩形类4.4 sizeDelta —— UI坐标4.5 anchoredPosition —— UI坐标5.RectTransform API 方法5.…

数据可视化 | Tableau从入门到高手 入门联接关系数据预处理

Tableau 人人可用、处处可用的分析 Tableau 是一个可视化分析平台&#xff0c;它改变了我们使用数据解决问题的方式&#xff0c;使个人和组织能够充分利用自己的数据。利用 Tableau 查看并理解任何数据。 Tableau Software 可以帮助人们查看并理解数据&#xff0c;可连接到几乎…

蓝桥杯实战应用【算法代码篇】-基于数组实现线性表

前言 线性表是由有限个具有相同性质的元素构成,结构上要求,非表头和表尾元素有且只有一个前驱和后继。对于表头和表尾元素,如果是没有环的线性表,则表头元素没有前驱,表尾元素没有后继。如果有环则均存在前驱和后继元素。对于线性结构,有两种保存的方法,一种是使用C语言…