Unity 3D编辑器扩展介绍、教程(二) —— 创建窗口
Unity编辑器扩展教程(二)
本文提供全流程,中文翻译。 Chinar坚持将简单的生活方式,带给世人! (拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例) |
此教程是在教程(一)基础上进行扩展:如果不知道如何创建编辑器按钮,推荐先看教程(一)
一
Brief Introduction —— 简介
我们在做工程的时候,需要对数据进行操作。
为节省时间,会使用一些快捷键,菜单栏上的功能、或是右键菜单
这些便捷的功能,都是Unity官方为了方便我们对所需数据进行操作。
对Unity编辑进行了一些封装处理,简化数据操作流程,封装为一个按钮/一个窗口/窗口功能。
这些诸如此类的功能就是编辑器的扩展,和封装
功能键、Inspector面板、Game视窗等等都是编辑器的功能
注意:编辑器类脚本,必须放在 Assets/Editor 资源目录中
此文件夹下的脚本只对编辑器进行操作。最后资源打包,Editor文件夹下的所有资源都不会被打包到工程中
如果没有此文件夹,需自行创建:在Project视窗下,右键Create - - Folder
二
ScriptableWizard —— 脚本化向导
ScriptableWizard 是一个编辑器类,继承自 EditorWindow
从这个类派生来创建一个编辑器向导
1
- - DisplayWizard —— 显示器向导
创建一个显示器向导,调用静态方法
DisplayWizard <类型>(“标题”, “第一个按钮”, “第二个按钮”);
即可创建一个 显示器向导
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,所以可以在其中直接调用)
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() 调用此函数,进度条才会被删除
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 窗口独立,不可合并
以下是我写的一个简单的梨子,用于批量修改物体的名称(选择物体内数组,并没有进行内部处理)
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
对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址
Unity 3D编辑器扩展介绍、教程(二) —— 创建窗口的更多相关文章
- Unity 3D编辑器扩展介绍、教程(一) —— 创建菜单项
Unity编辑器扩展教程 本文提供全流程,中文翻译.Chinar坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) 一 Brief Introduct ...
- Unity 3D UGUI Toggle用法教程
UGUI Toggle用法教程 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- 心分 ...
- unity shader 编辑器扩展类 ShaderGUI
这应该unity5才出的新功能了,今天看文档时刚巧看到了,就来尝试了一下. 效果如图: shader 的编辑器扩展分为2种方法: 是通过UnityEditor下的ShaderGUI类来实现的,形式比较 ...
- Unity3D编辑器扩展(六)——模态窗口
前面我们已经写了5篇关于编辑器的,这是第六篇,也是最后一篇: Unity3D编辑器扩展(一)——定义自己的菜单按钮 Unity3D编辑器扩展(二)——定义自己的窗口 Unity3D编辑器扩展(三)—— ...
- Jmeter 快速入门教程(二)--创建简单web测试
[版权所有: whoistester.com & jmeter.cf] http://wenku.baidu.com/linkurl=9zc4VHe6vUUeMdDZPpNsRehkazZFw ...
- [转]Unity 3D旋转矢量方向及二维平面基于一点选择另一点(Rotate a Vector3 direction & Rotate a point about another point in 2D )
http://specialwolf.blog.163.com/blog/static/124466832201301332432766/ ****************************** ...
- Spring Boot2 系列教程(二)创建 Spring Boot 项目的三种方式
我最早是 2016 年底开始写 Spring Boot 相关的博客,当时使用的版本还是 1.4.x ,文章发表在 CSDN 上,阅读量最大的一篇有 43W+,如下图: 2017 年由于种种原因,就没有 ...
- Arduino IDE for ESP8266教程(二) 创建WIFI AP模式
创建WIFI热点 #include <ESP8266WiFi.h> void setup() { Serial.begin ( 115200 ); Serial.println(" ...
- 2.Jmeter 快速入门教程(二)--创建简单web测试 打印 E-mail
今天我们就来实际用Jmeter创建一个测试场景,并进行性能测试. 注:由于本人使用中文版本,使用英文版本的请注意具体的菜单及参数名称. 1. 添加线程组(相当于lr里的scenario 设置) 打开j ...
随机推荐
- Use a layout_width of 0dip instead of fill_parent for better performance
安装了最新的ATD 18之后,新加的Lint Warnings插件会给我们检测出许多xml布局中不当的地方,例如: Use a layout_width of 0dip instead of fill ...
- 微服务设计 - api版本控制
要描述了几种API版本控制的方法.用户可以查询原始的API,或者添加定制的头文件来接收特定的版本.如果应用程序收到一个重大修订,将URI修改为V2.在进行迭代改进时,将创建与更改日期相一致的端点,并允 ...
- Spring源码的编译、下载和阅读
原文出处: 分享牛 想对spring框架进行深入的学习一下,看看源代码,提升和沉淀下自己,工欲善其事必先利其器,还是先搭建环境吧. 环境搭建 sping源码之前是svn管理,现在已经迁移到了githu ...
- C#实现的UDP收发请求工具类实例
本文实例讲述了C#实现的UDP收发请求工具类.分享给大家供大家参考,具体如下: 初始化: ListeningPort = int.Parse(ConfigurationManager.AppSetti ...
- English trip -- Review Unit8 Work 工作
工作一般询问对方的工作情况的方式: What job is it? 它的工作是什么? You're a engineer? 你是工程师? Right 是的 What do you do? ...
- mysql--------四种索引类型
一.索引的类型 mysql索引的四种类型:主键索引.唯一索引.普通索引和全文索引.通过给字段添加索引可以提高数据的读取速度,提高项目的并发能力和抗压能力.索引优化时mysql中的一种优化方式.索引的作 ...
- android--------Retrofit+RxJava的使用
Retrofit是Square公司开发的一款针对Android网络请求的一个当前很流行的网络请求库. http://square.github.io/retrofit/ https://github. ...
- C++&C#外挂(内存修改)
大学时候因为主修C#语言(当然现在做的是javaweb开发),那时在网上学了用C#做外挂的教程,外挂嘛,大家都懂的.这里只是低级的修改内存,不涉及到截获数据包.如果是欺骗服务器,修改服务器数据,那就难 ...
- HDU-1226 超级密码 (BFS+剪枝)
Problem Description Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息:密 码是一个C进 ...
- MySQL查看一个表的创建文本以及删除表某列的索引
#查看vrv_paw_area创建文本,使用这句话主要是为了找到该表对应字段上的索引名称show create table vrv_paw_area; #删除vrv_paw_area表的‘name’索 ...