Unity 3D编辑器扩展介绍、教程(一) —— 创建菜单项

简介: Unity编辑器扩展教程本文提供全流程,中文翻译。Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)...

Unity编辑器扩展教程


本文提供全流程,中文翻译。

Chinar坚持将简单的生活方式,带给世人!

(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例)




Brief Introduction —— 简介


我们在做工程的时候,需要对数据进行操作。

为节省时间,会使用一些快捷键,菜单栏上的功能、或是右键菜单

这些便捷的功能,都是Unity官方为了方便我们对所需数据进行操作。

对Unity编辑进行了一些封装处理,简化数据操作流程,封装为一个按钮/一个窗口/窗口功能。

这些诸如此类的功能就是编辑器的扩展,和封装

功能键、Inspector面板、Game视窗等等都是编辑器的功能


注意:编辑器类脚本,必须放在 Assets/Editor 资源目录中

此文件夹下的脚本只对编辑器进行操作。最后资源打包,Editor文件夹下的所有资源都不会被打包到工程中

如果没有此文件夹,需自行创建:在Project视窗下,右键Create - - Folder

举个栗子黑白88

这里写图片描述

这里写图片描述


Create MenuItem —— 创建菜单项


主要使用:静态方法

MenuItem (itemName : string, isValidateFunction : bool, priority : int)


1

- - Create Level 1 Menu —— 创建一级菜单


在菜单栏上创建一个菜单项,并创建一个一级菜单按钮

注意:编辑器类脚本,必须放在 Assets/Editor 资源目录中

此文件夹下的脚本只对编辑器进行操作。最后资源打包,Editor文件夹下的所有资源都不会被打包到工程中

如果没有此文件夹,需自行创建:在Project视窗下,右键Create - - Folder

举个栗子黑白88

using UnityEditor; //引用Unity编辑器命名空间
using UnityEngine; //引用Unity引擎命名空间


/// <summary>
/// 创建一个脚本工具类
/// </summary>
public class Tools//脚本无需继承自MonoBehaviour
{
    /// <summary>
    /// 创建新的菜单项
    /// </summary>
    /// //在菜单栏中创建一个 我的工具 菜单项目,并生成一个 “一级选项” 的按钮:需要对应一个静态方法(名字最好保持一致,不一致也可),方法体自由定义
    [MenuItem("我的工具/一级选项")] //菜单项(“菜单栏名称/子类名称”)—— 经过测试可为中文
    static void 一级选项()      //必须设置成静态方法 —— 经过测试,亦可为中文
    {
        Debug.Log(111);
    }
}

会有生成一个 一级选项 的按钮,点击后打印“111”
这里写图片描述


2

- - Create Level 2 Menu —— 创建二级菜单


在菜单栏上创建一个菜单项,并创建一个二级菜单按钮

举个栗子黑白88

using UnityEditor; //引用Unity编辑器命名空间
using UnityEngine; //引用Unity引擎命名空间


/// <summary>
/// 创建一个脚本工具类
/// </summary>
public class Tools//脚本无需继承自MonoBehaviour
{
    /// <summary>
    /// 创建二级菜单项
    /// </summary>
    /// //在菜单栏中创建一个 我的工具 菜单项目,并生成一个 “二级选项” 的按钮:需要对应一个静态方法(名字最好保持一致,不一致也可),方法体自由定义
    [MenuItem("我的工具/一级选项/二级选项")]    //菜单项(“菜单栏名称/子类名称”)—— 经过测试可为中文
    static void 二级选项() //必须设置成静态方法 —— 经过测试,亦可为中文
    {
        Debug.Log(222);
    }
}

会有生成一个 二级选项 的按钮,点击后打印“222”
这里写图片描述


3

- - Create Level 2 Menu in System Menu —— 在系统菜单中创建二级菜单


在系统菜单 Edit 中创建二级菜单

举个栗子黑白88

using UnityEditor; //引用Unity编辑器命名空间
using UnityEngine; //引用Unity引擎命名空间


/// <summary>
/// 创建一个脚本工具类
/// </summary>
public class Tools//脚本无需继承自MonoBehaviour
{
    /// <summary>
    /// 在系统默认的菜单项中,创建子按钮
    /// </summary>
    /// //在系统默认菜单项 Edit 中创建按钮:(名字最好保持一致,不一致也可)
    [MenuItem("Edit/一级选项/二级选项2")]    
    static void 二级选项2() 
    {
        Debug.Log(333);
    }
}

Edit 中最下方,会有生成一个 二级选项2 的按钮,点击后打印“333”
这里写图片描述


4

- - Menu grouping —— 菜单分组


完成菜单的分组,例如系统中的多个菜单项分组管理

静态方法 MenuItem (itemName : string, isValidateFunction : bool, priority : int)


MenuItem (表示菜单项:就是路径名 , 验证函数 : 同名的按钮在菜单函数调用之前调用 , 优先级:用来管理菜单项的层级关系)

注意: Priority 优先级如果设置为:-1 ,那么必然是在第一个

举个栗子黑白88

using UnityEditor; //引用Unity编辑器命名空间
using UnityEngine; //引用Unity引擎命名空间


/// <summary>
/// 创建一个脚本工具类
/// </summary>
public class Tools//脚本无需继承自MonoBehaviour
{
    /// <summary>
    /// 菜单分组 —— 层级10
    /// </summary>
    /// //每个菜单栏的 priority 属性:优先级默认为1000。相差 11 可以分为另一个组。也就是大于10就另建一组
    [MenuItem("按钮/功能1", false, 10)] 
    static void 功能1()
    {
        Debug.Log("功能1");
    }

    /// <summary>
    /// 菜单分组 —— 层级:如果不填,系统默认为1000,所以排序在最后
    /// </summary>
    [MenuItem("按钮/功能2")]
    static void 功能2()
    {
        Debug.Log("功能2");
    }


    /// <summary>
    /// 菜单分组 —— 层级:21
    /// </summary>
    /// //与按钮1的层级10,相差11,故而分到了另一组中
    [MenuItem("按钮/功能3", false, 21)]
    static void 功能3()
    {
        Debug.Log("功能3");
    }
}

菜单栏会有生成一个 功能 的菜单项,其中有:功能1/3/2。点击后分别打印“1/3/2”
这里写图片描述


5

- - Menu display and hide. —— 菜单的显示和隐藏


完成菜单的显示和隐藏,有些时候菜单项是灰色,不可用状态/可用状态

静态方法 MenuItem (itemName : string, isValidateFunction : bool, priority : int)


验证函数 isValidateFunction 值为 true 时,此验证函数下的函数方法,会在菜单函数之前调用

满足条件,则按钮显示/否则隐藏

注意: Hierarchy 面板中,右键菜单是 菜单栏里 GameObject 的菜单项。

所以在 GameObject 菜单栏中创建一个按钮,并且优先级设置到第一组中,即可在 Hierarchy 的右键菜单中显示 该按钮

注意: Priority 优先级如果设置为:-1 ,那么必然是在第一个
举个栗子黑白88

using UnityEditor; //引用Unity编辑器命名空间
using UnityEngine; //引用Unity引擎命名空间


/// <summary>
/// 创建一个脚本工具类
/// </summary>
public class Tools//脚本无需继承自MonoBehaviour
{
    /// <summary>
    /// 验证“删除物体”按钮的 显示/隐藏
    /// </summary>
    [MenuItem("GameObject/删除物体", true, -1)]
    static bool 删除物体Alternative()
    {
        if (Selection.objects.Length > 0)//如果选择了物体
        {
            return true;//就返回真:按钮可用
        }
        else//否则
        {
            return false;//返回假:按钮不可用
        }
    }


    /// <summary>
    /// 在系统默认的菜单项 GameObject 中,创建 删除物体 按钮,优先级第一个
    /// </summary>
    [MenuItem("GameObject/删除物体", false, -1)]
    static void 删除物体()
    {
        //Selection.objects 返回值是一个 Object数组,就是选中的所有物体
        foreach (var o in Selection.objects) //遍历选中的所有物体
        {
            //GameObject.DestroyImmediate(o);//直接删除,但是无法撤销
            Undo.DestroyObjectImmediate(o); //直接删除,但是可以撤销(用Ctrl+z)//Immediate:直接的,立即的
        }
    }
}

菜单栏 GameObject 会有生成一个 删除物体 的菜单项

如果选了物体,按钮可用

否则不可用
这里写图片描述


6

- - Shortcuts —— 快捷键


完成对菜单项目的快捷键设置

静态方法 MenuItem (itemName : string)


参数 itemName 为字符串,表示菜单项。+ 空格 + _O)就表示快捷键设为 O 键,不区分大小写
参数 itemName 为字符串,表示菜单项。+ 空格 + %l)就表示组合键设为 Ctrl+L 键,不区分大小写

注意:名字和快捷键中间必须要有空格

组合键: % : Ctrl
组合键: # : Shift
组合键: & : Altl
举个栗子黑白88

using UnityEditor; //引用Unity编辑器命名空间
using UnityEngine; //引用Unity引擎命名空间


/// <summary>
/// 创建一个脚本工具类
/// </summary>
public class Tools//脚本无需继承自MonoBehaviour
{
       /// <summary>
    /// 快捷键测试
    /// </summary>
    [MenuItem("我的工具/快捷键测试 _o")]//_o 是指定快捷键 O ,并不区分大小写 (名字和快捷键中间必须要有空格)
    static void 选中物体个数()
    {
        Debug.Log("快捷键"+Selection.objects.Length);//打印选中物体的个数
    }


    /// <summary>
    /// 在系统默认的菜单项中,创建子按钮
    /// </summary>
    /// % : Ctrl
    /// # : Shift
    /// & : Alt
    [MenuItem("我的工具/组合键测试 %l")] //%l 是指定组合键:Ctrl+L,并不区分大小写 (名字和快捷键中间必须要有空格)
    static void 快捷键测试()
    {
        Debug.Log("组合键"+ Selection.activeGameObject.name); //打印物体名/—— 默认打印第一个选中的物体,无论选中了几个
    }
}

点击键盘按钮 O ,即可打印 “选择物体的个数”

点击键盘按钮 Ctrl + L ,即可打印 “所选物体的名字”:
如果选择多个,默认打印第一个(根据自己代码来判定,如有需要可自己写)
这里写图片描述


Create MenuItem for the Component —— 创建组件上的菜单项


主要使用:静态方法

MenuCommand : Context —— 菜单命令的目标对象


1

- - Script Component —— 在脚本组件上添加菜单项


静态方法 MenuItem (itemName : string)


参数 itemName 为字符串,表示菜单项。

参数 “CONTEXT/ PlayerHealth” 为 组件 路径

若想对某个(组件/脚本)进行操作,必须写上 “CONTEXT/ (组件/脚本)名

Undo.RecordObject (对象,键) 此函数用于记录对象之后的数据变化,没有则不能回退操作
举个栗子黑白88

using UnityEditor; //引用Unity编辑器命名空间
using UnityEngine; //引用Unity引擎命名空间


/// <summary>
/// 玩家脚本上的工具 —— 测试脚本
/// </summary>
public class PlayerTools
{
    /// <summary>
    /// 给玩家脚本组件上添加按钮:初始化人物
    /// </summary>
    /// //[菜单项函数(“环境(组件:想要给组件上加必须要用这个来表示路径)/所需控制组件(脚本名)/需要执行的方法名(就是按钮名)”)]
    [MenuItem("CONTEXT/PlayerHealth/初始化人物")]
    static void 初始化人物(MenuCommand command) //MenuCommand 正在操作的组件对象类
    {
        CompleteProject.PlayerHealth player = (CompleteProject.PlayerHealth) command.context; //声明一个PlayerHealt对象 th  —— 需要强转为 PlayerHealth类型
        Undo.RecordObject(player, "PlayerTools_player");                                      //记录对象 player 之后的数据变化,用于回退 —— 记录对象(对象,键);//键的名字随意,不能重复//如果没有这句话,是不能退会之前的修改的
        player.startingHealth = 100;                                                          //血量初始化到100
    }
}

右键点击组件 ,选择 初始化人物 : 即可完成对血量的初始化 —— Ctrl+z,回退操作

这里写图片描述


2

- - Syetem Component —— 在系统组件上添加菜单项


静态方法 MenuItem (itemName : string)


参数 itemName 为字符串,表示菜单项。

参数 “CONTEXT/ Rigidbody” 为 组件 路径

若想对某个(组件/脚本)进行操作,必须写上 “CONTEXT/ (组件/脚本)名

Undo.RecordObject (对象,键) 此函数用于记录对象之后的数据变化,没有则不能回退操作

举个栗子黑白88

using UnityEditor; //引用Unity编辑器命名空间
using UnityEngine; //引用Unity引擎命名空间


/// <summary>
/// 玩家脚本上的工具 —— 测试脚本
/// </summary>
public class PlayerTools
{
    /// <summary>
    /// 给系统组件 Rigidbody 上添加按钮:取消重力
    /// </summary>
    /// <param name="command"></param>
    [MenuItem("CONTEXT/Rigidbody/取消重力")]
    static void 取消重力(MenuCommand command)
    {
        Rigidbody rig = (Rigidbody) command.context; //context是一个 (正操作/鼠标下) 的组件:返回值为Object —— 强转为需要的类型
        Undo.RecordObject(rig, "PlayerTools_rig");   //记录 rig 之后的数据变化,用于回退 —— 记录对象(对象,键);//键的名字随意,不能重复//没有这句话,是不能回退,因为系统没记录
        rig.mass       = 0;                          //质量为0
        rig.useGravity = false;                      //关闭重力
    }
}

右键点击刚体组件 ,选择 取消重力: 即可完成对重力的取消 —— Ctrl+z,完成回退

这里写图片描述


3

- - ContextMenu —— 组件菜单的用法


ContextMenu ContextMenuItem 均继承自: MonoBehaviour

所以可以直接在 自义定脚本中使用,也就是工程脚本中直接用



[ContextMenuItem(按钮名,方法名)] 需要写在所需控制变量之上

[ContextMenu(按钮名)] 需要直接写在方法上

Undo.RecordObject (对象,键) 此函数用于记录对象之后的数据变化,没有则不能回退操作

举个栗子黑白88

using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;


/// <summary>
/// 玩家健康属性脚本
/// </summary>
public class PlayerHealth : MonoBehaviour
{
    [ContextMenuItem("增加血量50", "增加血量")]                    //按钮名,方法//需要写在所需控制变量之上
    public int startingHealth = 100;                            // 初始血量
       /// <summary>
        /// 直接在脚本中设置菜单项,即可在 面板中右键显示 该按钮
        /// </summary>
        [ContextMenu("设置属性")]//可以直接在脚本方法里写,需要直接写在方法上
        void 设置属性()
        {
            Debug.Log("设置属性");
        }


        /// <summary>
        /// 为变量 startingHealth 提供方法,每点击一次加 50
        /// </summary>
        void 增加血量()
        {
            Undo.RecordObject(this, "PlayerHealth_startingHealth");//记录值的改变,用于回退//(对象,键)
            startingHealth += 50;
        }
}

右键点击 PlayerHealth 脚本组件 ,即可看到按钮“设置属性”

点击 PlayerHealth 脚本组件 ,选择 startingHealth 属性,右键即可看到按钮“增加血量50”

这里写图片描述


END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

相关文章
|
15天前
Axure设计之文本编辑器制作教程
本文介绍如何在Axure中模拟Web端富文本编辑器,实现基本的文本编辑功能,包括自定义字体样式、大小、颜色及对齐方式等。通过拖入矩形、文本域等元件,添加单选框和图标,并设置相应的交互,完成文本编辑器的制作。
|
3月前
|
图形学 开发者 存储
超越基础教程:深度拆解Unity地形编辑器的每一个隐藏角落,让你的游戏世界既浩瀚无垠又细节满满——从新手到高手的全面技巧升级秘籍
【8月更文挑战第31天】Unity地形编辑器是游戏开发中的重要工具,可快速创建复杂多变的游戏环境。本文通过比较不同地形编辑技术,详细介绍如何利用其功能构建广阔且精细的游戏世界,并提供具体示例代码,展示从基础地形绘制到植被与纹理添加的全过程。通过学习这些技巧,开发者能显著提升游戏画面质量和玩家体验。
156 3
|
3月前
|
开发者 图形学 开发工具
Unity编辑器神级扩展攻略:从批量操作到定制Inspector界面,手把手教你编写高效开发工具,解锁编辑器隐藏潜能
【8月更文挑战第31天】Unity是一款强大的游戏开发引擎,支持多平台发布与高度可定制的编辑器环境。通过自定义编辑器工具,开发者能显著提升工作效率。本文介绍如何使用C#脚本扩展Unity编辑器功能,包括批量调整游戏对象位置、创建自定义Inspector界面及项目统计窗口等实用工具,并提供具体示例代码。理解并应用这些技巧,可大幅优化开发流程,提高生产力。
369 1
|
3月前
|
图形学 数据可视化 开发者
超实用Unity Shader Graph教程:从零开始打造令人惊叹的游戏视觉特效,让你的作品瞬间高大上,附带示例代码与详细步骤解析!
【8月更文挑战第31天】Unity Shader Graph 是 Unity 引擎中的强大工具,通过可视化编程帮助开发者轻松创建复杂且炫酷的视觉效果。本文将指导你使用 Shader Graph 实现三种效果:彩虹色渐变着色器、动态光效和水波纹效果。首先确保安装最新版 Unity 并启用 Shader Graph。创建新材质和着色器图谱后,利用节点库中的预定义节点,在编辑区连接节点定义着色器行为。
261 0
|
3月前
|
图形学 数据安全/隐私保护 iOS开发
Unity与IOS⭐Xcode打包,上架TestFlight的完整教程
Unity与IOS⭐Xcode打包,上架TestFlight的完整教程
|
3月前
|
Apache 图形学
WebGL☀️Unity WebGL适配到各平台的教程
WebGL☀️Unity WebGL适配到各平台的教程
|
3月前
|
存储
UE建模模式编辑器工具的快速入门教程
在UE虚幻引擎中,想要进行创建网格体、制作新关卡几何原型、编辑现有静态网格体资产等模型编辑动作,都需要借助建模模式的编辑器完成。因此,充分掌握编辑器能力是每个UE开发人员必备的基础技能,尽管UE建模模式中的许多工具与其他建模软件工具操作类似,但在如何构建网格体编辑方面存在着重要区别。 下面就带大家一起了解「UE建模模式编辑器」的不同之处🤔。
|
3月前
|
图形学 C#
超实用!深度解析Unity引擎,手把手教你从零开始构建精美的2D平面冒险游戏,涵盖资源导入、角色控制与动画、碰撞检测等核心技巧,打造沉浸式游戏体验完全指南
【8月更文挑战第31天】本文是 Unity 2D 游戏开发的全面指南,手把手教你从零开始构建精美的平面冒险游戏。首先,通过 Unity Hub 创建 2D 项目并导入游戏资源。接着,编写 `PlayerController` 脚本来实现角色移动,并添加动画以增强视觉效果。最后,通过 Collider 2D 组件实现碰撞检测等游戏机制。每一步均展示 Unity 在 2D 游戏开发中的强大功能。
182 6
|
2月前
|
测试技术 C# 图形学
掌握Unity调试与测试的终极指南:从内置调试工具到自动化测试框架,全方位保障游戏品质不踩坑,打造流畅游戏体验的必备技能大揭秘!
【9月更文挑战第1天】在开发游戏时,Unity 引擎让创意变为现实。但软件开发中难免遇到 Bug,若不解决,将严重影响用户体验。调试与测试成为确保游戏质量的最后一道防线。本文介绍如何利用 Unity 的调试工具高效排查问题,并通过 Profiler 分析性能瓶颈。此外,Unity Test Framework 支持自动化测试,提高开发效率。结合单元测试与集成测试,确保游戏逻辑正确无误。对于在线游戏,还需进行压力测试以验证服务器稳定性。总之,调试与测试贯穿游戏开发全流程,确保最终作品既好玩又稳定。
112 4
|
3月前
|
图形学 缓存 算法
掌握这五大绝招,让您的Unity游戏瞬间加载完毕,从此告别漫长等待,大幅提升玩家首次体验的满意度与留存率!
【8月更文挑战第31天】游戏的加载时间是影响玩家初次体验的关键因素,特别是在移动设备上。本文介绍了几种常见的Unity游戏加载优化方法,包括资源的预加载与异步加载、使用AssetBundles管理动态资源、纹理和模型优化、合理利用缓存系统以及脚本优化。通过具体示例代码展示了如何实现异步加载场景,并提出了针对不同资源的优化策略。综合运用这些技术可以显著缩短加载时间,提升玩家满意度。
173 5
下一篇
无影云桌面