Unity 3D编辑器扩展介绍、教程(二) —— 创建窗口

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

Unity编辑器扩展教程(二)


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

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

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




此教程是在教程(一)基础上进行扩展:如果不知道如何创建编辑器按钮,推荐先看教程(一)

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


Brief Introduction —— 简介


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

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

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

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

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

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


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

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

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

举个栗子黑白88

这里写图片描述

这里写图片描述


ScriptableWizard —— 脚本化向导


ScriptableWizard 是一个编辑器类,继承自 EditorWindow

从这个类派生来创建一个编辑器向导


1

- - DisplayWizard —— 显示器向导


创建一个显示器向导,调用静态方法

DisplayWizard <类型>(“标题”, “第一个按钮”, “第二个按钮”);

即可创建一个 显示器向导

举个栗子黑白88

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


/// <summary>
/// 改变所有敌人脚本
/// </summary>
public class ChangeAll : ScriptableWizard
{
    public int AddHp = 10; //每次增加血量值
    public int Num = 0;//一个数字为了测试 isValue

    /// <summary>
    /// 菜单栏 我的工具 中,创建一个按钮
    /// </summary>
    [MenuItem("我的工具/修改所有敌人属性")]
    static void 修改所有敌人属性()
    {
        //显示器向导 <所管控的类>( 窗口的名字,窗口中按钮的名字,第二个按钮的名字 );
        DisplayWizard<ChangeAll>("修改所有敌人血量", "确认修改血量", "第二个按钮");
    }
}

这里写图片描述


2

- - ScriptableWizard Messages Sent —— 脚本化向导的信息传递


其中内置了一些固定函数,用来传递信息

OnEnable() —————————————————– 脚本有效时就会执行

OnWizardCreate() ————————————— 在 创建 / 第一个 按钮上点击时调用

OnWizardOtherButton() ————————— 在 其他 按钮上点击时调用(允许一个动作)

OnWizardUpdate() ————————————– 在向导被打开 / 向导中数据发生变化时被调用

OnSelectionChange() ——————————— 当选择发生改变,调用此函数
(此函数在EditorWindow中,而ScriptableWizard继承自EditorWindow,所以可以在其中直接调用)
举个栗子黑白88

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


/// <summary>
/// 改变所有敌人脚本
/// </summary>
public class ChangeAll : ScriptableWizard
{
    public int AddHp = 10; //每次增加血量值
    public int Num   = 0;  //一个数字为了测试 isValue


    /// <summary>
    /// 菜单栏 我的工具 中,创建一个按钮
    /// </summary>
    [MenuItem("我的工具/修改所有敌人属性")]
    static void 修改所有敌人属性()
    {
        //显示器向导 <所管控的类>( 窗口的名字,窗口中按钮的名字,第二个按钮的名字 );
        DisplayWizard<ChangeAll>("修改所有敌人血量", "确认修改血量", "第二个按钮");
    }


    /// <summary>
    /// 固定函数名:窗口开始时执行
    /// </summary>
    void OnEnable()
    {
        AddHp = EditorPrefs.GetInt("ChangeAll_health", AddHp); //取值,默认为初始值   并赋值给AddHp
    }


    /// <summary>
    /// 固定函数名:对应现实向导中的第一个按钮 —— 确认修改血量
    /// </summary>
    void OnWizardCreate()
    {
        //进度条
        EditorUtility.DisplayProgressBar("修改进度", "0/" + Selection.gameObjects.Length + "完成修改", 1);
        int count = 0;

        foreach (var gameObject in Selection.gameObjects) //遍历选中的物体
        {
            CompleteProject.EnemyHealth health = gameObject.GetComponent<CompleteProject.EnemyHealth>(); //获取其身上脚本组件
            Undo.RecordObject(health, "Change health");                                                  //记录变量 health 之后做的更改
            health.startingHealth += AddHp;                                                              //自增 设置的值   //需要修改其他属性,自己往下写

            count++;
            //进度条
            EditorUtility.DisplayProgressBar("修改进度", count + "/" + Selection.gameObjects.Length + "完成修改", progress: count / Selection.gameObjects.Length);
        }
        EditorUtility.ClearProgressBar();//清除进度条
    }


    /// <summary>
    /// 固定函数名:对应现实向导中的第二按钮 —— 第二个按钮
    /// </summary>
    void OnWizardOtherButton()
    {
        //弹出通知(新建一个 GUI内容(被选中物体的个数)+“字符” )
        ShowNotification(new GUIContent(Selection.gameObjects.Length + "个元素被选中"));
    }


    /// <summary>
    /// 当属性值被修改时,每帧调用。 /  当界面开启时,会调用一次
    /// </summary>
    void OnWizardUpdate()
    {
        helpString  = null; //每次调用就归零一次,否则会出现字体不消除的情况
        errorString = null;

        if (Selection.gameObjects.Length > 0)
        {
            helpString = "当前选择了" + Selection.gameObjects.Length + "个敌人"; //及时更新选择的数量
        }
        else
        {
            errorString = "最少选择一个啊"; //错误提示
        }

        EditorPrefs.SetInt("ChangeAll_health", AddHp); //修改后存入一个值,就是记录一下。
    }


    /// <summary>
    /// 当选择的物体发生改变,调用此函数
    /// </summary>
    void OnSelectionChange()
    {
        OnWizardUpdate();
    }
}

这里写图片描述


3

- - DisplayProgressBar —— 进度条


在显示器向导中创建一个进度条

EditorUtility.DisplayProgressBar( 进度条标题,进度信息,进度比例 )

EditorUtility.ClearProgressBar() 调用此函数,进度条才会被删除
举个栗子黑白88

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


/// <summary>
/// 改变所有敌人脚本
/// </summary>
public class ChangeAll : ScriptableWizard
{
    public int AddHp = 10; //每次增加血量值
    public int Num   = 0;  //一个数字为了测试 isValue


    /// <summary>
    /// 菜单栏 我的工具 中,创建一个按钮
    /// </summary>
    [MenuItem("我的工具/修改所有敌人属性")]
    static void 修改所有敌人属性()
    {
        //显示器向导 <所管控的类>( 窗口的名字,窗口中按钮的名字,第二个按钮的名字 );
        DisplayWizard<ChangeAll>("修改所有敌人血量", "确认修改血量", "第二个按钮");
    }


    /// <summary>
    /// 固定函数名:对应现实向导中的第二按钮 —— 第二个按钮
    /// </summary>
    void OnWizardOtherButton()
    {
        EditorUtility.DisplayProgressBar("修改进度", "0/" + Selection.gameObjects.Length + "完成修改", 1); //进度条
        int count = 0;                                                                             //计数
        foreach (var gameObject in Selection.gameObjects)                                          //遍历选中的物体
        {
            CompleteProject.EnemyHealth health = gameObject.GetComponent<CompleteProject.EnemyHealth>();                                         //获取其身上脚本组件
            Undo.RecordObject(health, "Change health");                                                                                          //记录变量 health 之后做的更改
            health.startingHealth += AddHp;                                                                                                      //自增 设置的值   //需要修改其他属性,自己往下写
            count++;                                                                                                                             //计数自增1
            EditorUtility.DisplayProgressBar("修改进度", count + "/" + Selection.gameObjects.Length + "完成修改", count / Selection.gameObjects.Length); //进度条
        }

        //EditorUtility.ClearProgressBar(); //清除进度条(只有调用此方法,进度条才会删除)
    }
}

这里写图片描述


EditorWindow —— 编辑器窗口


创建一个编辑器窗口,在我们的Unity编辑器中

GetWindow(bool, 窗口名字)

bool 值为: false 窗口可以与其他窗口合并
bool 值为: true 窗口独立,不可合并

以下是我写的一个简单的梨子,用于批量修改物体的名称(选择物体内数组,并没有进行内部处理)
举个栗子黑白88

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


/// <summary>
/// 创建一个窗口类
/// </summary>
public class ChinarWindow : EditorWindow//继承自 EditorWindow
{
    string      CustomName = "CustomName"; //自定义名字
    private int ChinarNum  = 0;            //空物体数量


    /// <summary>
    /// 创建一个菜单项
    /// </summary>
    [MenuItem("我的工具/显示新窗口")]
    static void 显示新窗口()
    {
        ChinarWindow chinar = GetWindow<ChinarWindow>(false, "Chinar窗口"); //获取到一个窗口,赋值给当前编辑器类的对象
        chinar.Show();                                                    //显示对象的窗口
    }


    /// <summary>
    /// 此函数中实现编辑器界面的定义/绘制
    /// </summary>
    void OnGUI()
    {
        GUILayout.Label("这是Chianr窗口");                                     //标题
        CustomName = GUILayout.TextField(CustomName);                      //文本框
        ChinarNum  = int.Parse(GUILayout.TextField(ChinarNum.ToString())); //数字框

        //可以直接判断按钮的点击
        if (GUILayout.Button("修改所有物体名字"))
        {
            for (int i = 0; i < Selection.transforms.Length; i++) //遍历选中的元素
            {
                Undo.RecordObjects(Selection.gameObjects as GameObject[], "ChinarWindow_GameObject[]"); //Selection.gameObjects 返回一个GameObject[] ,并记录键(用于回退)
                Selection.transforms[i].SetSiblingIndex(i);                                             //为选择的物体设置下标
                Selection.transforms[i].name = CustomName + i;                                          //设置名字+i
            }
        }

        //判断按钮的点击
        if (GUILayout.Button("创建多个空物体"))
        {
            if (ChinarNum <= 0) //如果数字 小于等于 0
            {
                ShowNotification(new GUIContent("请写入创建空物体数量")); //提示 输入
            }
            else //不为0
            {
                for (int i = 0; i < ChinarNum; i++) //遍历个数
                {
                    Undo.RegisterCreatedObjectUndo(new GameObject(CustomName), "Chinar Create gameobject"); //创建一个名为 CustomName 的空物体
                }
            }
        }
    }
}

仔细看


END

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

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

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

相关文章
|
6天前
|
设计模式 存储 人工智能
深度解析Unity游戏开发:从零构建可扩展与可维护的游戏架构,让你的游戏项目在模块化设计、脚本对象运用及状态模式处理中焕发新生,实现高效迭代与团队协作的完美平衡之路
【9月更文挑战第1天】游戏开发中的架构设计是项目成功的关键。良好的架构能提升开发效率并确保项目的长期可维护性和可扩展性。在使用Unity引擎时,合理的架构尤为重要。本文探讨了如何在Unity中实现可扩展且易维护的游戏架构,包括模块化设计、使用脚本对象管理数据、应用设计模式(如状态模式)及采用MVC/MVVM架构模式。通过这些方法,可以显著提高开发效率和游戏质量。例如,模块化设计将游戏拆分为独立模块。
29 3
|
7天前
|
图形学 开发者 存储
超越基础教程:深度拆解Unity地形编辑器的每一个隐藏角落,让你的游戏世界既浩瀚无垠又细节满满——从新手到高手的全面技巧升级秘籍
【8月更文挑战第31天】Unity地形编辑器是游戏开发中的重要工具,可快速创建复杂多变的游戏环境。本文通过比较不同地形编辑技术,详细介绍如何利用其功能构建广阔且精细的游戏世界,并提供具体示例代码,展示从基础地形绘制到植被与纹理添加的全过程。通过学习这些技巧,开发者能显著提升游戏画面质量和玩家体验。
34 3
|
7天前
|
开发者 图形学 开发工具
Unity编辑器神级扩展攻略:从批量操作到定制Inspector界面,手把手教你编写高效开发工具,解锁编辑器隐藏潜能
【8月更文挑战第31天】Unity是一款强大的游戏开发引擎,支持多平台发布与高度可定制的编辑器环境。通过自定义编辑器工具,开发者能显著提升工作效率。本文介绍如何使用C#脚本扩展Unity编辑器功能,包括批量调整游戏对象位置、创建自定义Inspector界面及项目统计窗口等实用工具,并提供具体示例代码。理解并应用这些技巧,可大幅优化开发流程,提高生产力。
27 1
|
7天前
|
图形学 数据可视化 开发者
超实用Unity Shader Graph教程:从零开始打造令人惊叹的游戏视觉特效,让你的作品瞬间高大上,附带示例代码与详细步骤解析!
【8月更文挑战第31天】Unity Shader Graph 是 Unity 引擎中的强大工具,通过可视化编程帮助开发者轻松创建复杂且炫酷的视觉效果。本文将指导你使用 Shader Graph 实现三种效果:彩虹色渐变着色器、动态光效和水波纹效果。首先确保安装最新版 Unity 并启用 Shader Graph。创建新材质和着色器图谱后,利用节点库中的预定义节点,在编辑区连接节点定义着色器行为。
36 0
|
25天前
|
API 图形学
Unity精华☀️Audio Mixer终极教程:用《双人成行》讲解它的用途
Unity精华☀️Audio Mixer终极教程:用《双人成行》讲解它的用途
|
7天前
|
图形学 C++ C#
Unity插件开发全攻略:从零起步教你用C++扩展游戏功能,解锁Unity新玩法的详细步骤与实战技巧大公开
【8月更文挑战第31天】Unity 是一款功能强大的游戏开发引擎,支持多平台发布并拥有丰富的插件生态系统。本文介绍 Unity 插件开发基础,帮助读者从零开始编写自定义插件以扩展其功能。插件通常用 C++ 编写,通过 Mono C# 运行时调用,需在不同平台上编译。文中详细讲解了开发环境搭建、简单插件编写及在 Unity 中调用的方法,包括创建 C# 封装脚本和处理跨平台问题,助力开发者提升游戏开发效率。
17 0
|
24天前
|
图形学 数据安全/隐私保护 iOS开发
Unity与IOS⭐Xcode打包,上架TestFlight的完整教程
Unity与IOS⭐Xcode打包,上架TestFlight的完整教程
|
24天前
|
Apache 图形学
WebGL☀️Unity WebGL适配到各平台的教程
WebGL☀️Unity WebGL适配到各平台的教程
|
25天前
|
存储
UE建模模式编辑器工具的快速入门教程
在UE虚幻引擎中,想要进行创建网格体、制作新关卡几何原型、编辑现有静态网格体资产等模型编辑动作,都需要借助建模模式的编辑器完成。因此,充分掌握编辑器能力是每个UE开发人员必备的基础技能,尽管UE建模模式中的许多工具与其他建模软件工具操作类似,但在如何构建网格体编辑方面存在着重要区别。 下面就带大家一起了解「UE建模模式编辑器」的不同之处🤔。
|
25天前
|
开发工具 图形学 Android开发
Pico Neo 3教程☀️ 二、从 PicoVR Unity SDK 迁移至 Unity XR SDK
Pico Neo 3教程☀️ 二、从 PicoVR Unity SDK 迁移至 Unity XR SDK

热门文章

最新文章

下一篇
DDNS