正所谓:人靠衣装,佛靠金装。学会插件开发,成就大神人生。

  • 欢迎关注公众号:雷潮课堂

编辑器开发

一、课程内容

1-1本课程目标
1-2插件开发的起因
1-3插件的作用

二、菜单项制作

2-1菜单项(MenuItem)
2-2组件菜单(AddComponentMenu)
2-3上下文菜单(ContextMenu)
2-4必要组件菜单(RequireComponent)

三、自定义InsPector界面

3-1属性相关标识(HideInInspector,SerializeField,NonSerialized,Serializable)
3-2自定义界面属性 (CustomEditor)
3-3自定序列化属性字段 (PropertyField)

四、 自定义操作界面(Window)

4-1Windows窗口
4-2界面的生命周期(事件)
4-3编辑器下的UI控件
文本颜色字段,标签字段,数字输入字段,滑动条,位置大小输入字段,选择字段,标签、层、对象选择字段,单选字段,分组字段,其他字段

1-1本课程目标

学会自定义编辑器,开发一款属于自己的编辑器插件

1-2插件开发的起因

如果一个模型师想要在Unity中查看效果,但是她又是程序小白,作为公司一员应该给到她非常好帮助,比如制作一套工具集合(插件),让她根本离不开你。

1-3插件的作用

帮助企业建立技术护城河,提高开发效率,减少沟通成本,减少工作。

2-1菜单项

Asset目录下新建一个Editor文件夹,新建MyEditor脚本

using UnityEngine;
using UnityEditor; // 引用命名空间public class MyEditor : Editor   // 继承Editor类
{// 添加工具栏并设置创建方块方法 (false)显示出来[MenuItem("工具/创建方块, &_f",false)]  // % Ctrl  & Alt # Shiftpublic static void CreatCube(){   GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);cube.name = "方块";}// 用来处理编辑器的问题(Update)  private void OnSceneGUI(){     if (Input.GetKeyDown(KeyCode.F) && Input.GetKeyDown(KeyCode.LeftAlt)){CreatCube();}}
  • 效果图:

  • 注意

OnSceneGUI方法中主要使用Handles系列来绘制可视化调试控件,比如线、盒子、球体、文本等(可以自行操作)

private void OnSceneGUI()
{Handles.color = Color.green;
}
  • 2-1-1多级菜单:

using UnityEngine;
using UnityEditor; // 引用命名空间public class MyEditor : Editor   // 继承Editor类
{public static GameObject cube;// 添加工具栏并设置创建方块方法 (false)显示出来[MenuItem("工具/创建方块, &_f",false)]  // # Ctrl  & Altpublic static void CreatCube(){   cube = GameObject.CreatePrimitive(PrimitiveType.Cube);cube.name = "方块";}// 添加工具栏并设置创建方块方法 (false)显示出来[MenuItem("工具/销毁方块, &_G", false)]  // # 表示Ctrl  & 表示Altpublic static void DestroyCube(){if (cube == null){cube = GameObject.Find("方块");}Editor.Destroy(cube);}// 用来处理编辑器的问题(Scene绘制图形方法类似Update)private void OnSceneGUI(){Handles.color = Color.green;if (Input.GetKeyDown(KeyCode.F) && Input.GetKeyDown(KeyCode.LeftAlt)){CreatCube();}if (Input.GetKeyDown(KeyCode.G) && Input.GetKeyDown(KeyCode.LeftAlt)){DestroyCube();}}
}
2-2组件菜单(AddComponentMenu)
using UnityEngine;
//给Component菜单下增加One子菜单,并将TestOne类添加到对象上
[AddComponentMenu("One",1)]
public class TestOne : MonoBehaviour
{
}

2-3上下文菜单(ContextMenu)

在面板中右键出现的菜单

public class TestOne : MonoBehaviour
{[ContextMenu("测试")]public void Test(){Debug.Log("123");}
}
2-4必要组件菜单(RequireComponent)

using UnityEngine;[RequireComponent(typeof(Rigidbody))] // 添加组件必须要加上刚体
//给Component菜单下增加One子菜单,并将TestOne类添加到对象上
[AddComponentMenu("One",1)]
public class TestOne : MonoBehaviour
{}
3-1属性相关标识
  • 隐藏属性显示 (HideInInspector)
  • 不显示的属性(SerializeField)
  • 关键字序列化(Serializable) (针对类,结构体,枚举,委托有效)
  • 不会被序列(NonSerialized)
using System;
using UnityEngine;[Serializable] // 可以使类显示在视图面板
public enum MyColor
{red,green,blue
}
public class TestOne : MonoBehaviour
{[HideInInspector]public int age; //  将显示的属性隐藏[SerializeField]private float height; // 显示隐藏的属性[NonSerialized]public Vector3 v = new Vector3(10, 0, 0); // 防止变量序列化public MyColor c;
}
3-2自定义界面属性
  • 自定义显示面板(CustomEditor)

我们添加系统组件的时候,发现面板很好看,而脚本做不到这种效果。这里就需要自定义显示面板,如下图所示:

using UnityEngine;
using UnityEditor;// 引用命名空间// CustomEditor是对应标识的组件脚本
[CustomEditor(typeof(BoxCollider))] // 设置自定义BoxCollider的内容
public class MyInsPectorTest : Editor // 继承Editor类
{private bool b;private string s = "";private string m;// 重写Editor 绘制面板图形界面方法public override void OnInspectorGUI() {// 当我们使用自动布局技术的时候,就不要混合使用GUI.Lable,以免产生不必要的约束问题 GUILayout.Label("雷潮");b = GUILayout.Toggle(b,"关闭音效");GUILayout.Label("请输入账号");s = GUILayout.TextField(s);GUILayout.Label("请输入密码");m = GUILayout.PasswordField(m,'*'); // 后面是占位符,将密码字符更替为*if (GUILayout.Button("登录")){if (s == "leichao" && m == "123456"){Debug.Log("登录成功");}else{Debug.Log("账号或者密码错误");}}}
}
3-3自定序列化属性字段 (PropertyField)

命名空间在UnityEditor
SerializedObject 序列化对象 请点击查看序列化对象类
SerializedProperty 序列化属性 请点击查看序列化属性类

using System;
using UnityEngine;[Serializable] // 可以使类显示在视图面板
public enum MyColor
{red,green,blue
}
public class TestOne : MonoBehaviour
{public int age; public float height;public Vector3 v = new Vector3(10, 0, 0);public MyColor c;
}
using UnityEditor;[CustomEditor(typeof(TestOne))]
public class Test1 : Editor
{public SerializedObject mObj;public SerializedProperty mAge;public SerializedProperty mHeight;public SerializedProperty mVector;public SerializedProperty mColor;private void OnEnable(){mObj = new SerializedObject(target); // 创建一个目标,即挂载脚本物体mAge = this.mObj.FindProperty("age");mHeight = this.mObj.FindProperty("height");mVector = this.mObj.FindProperty("v");mColor = this.mObj.FindProperty("c");}public override void OnInspectorGUI(){this.mObj.Update();EditorGUILayout.PropertyField(this.mAge);EditorGUILayout.PropertyField(this.mHeight);EditorGUILayout.PropertyField(this.mVector);EditorGUILayout.PropertyField(this.mColor, true);}
}
4.自定义窗口菜单
4-1自定义窗口

using UnityEngine;
using UnityEditor;public class MyWindow :EditorWindow
{private bool b;private string s;private string m;private Color c = Color.white;private string t;[MenuItem("Tools/Window")]public static void ShowW(){EditorWindow.GetWindow<MyWindow>().Show();}private void OnGUI(){// 编辑MyWindowEditorGUILayout.LabelField("雷潮邀请你输入");EditorGUILayout.Space(); // 隔开一行EditorGUILayout.LabelField("请输入账号");s = EditorGUILayout.TextField(s);EditorGUILayout.SelectableLabel("请输入密码");s = EditorGUILayout.PasswordField(s);EditorGUILayout.Space(); // 隔开一行EditorGUILayout.LabelField("请选择颜色");this.c = EditorGUILayout.ColorField(c);EditorGUILayout.Space(); // 隔开一行EditorGUILayout.LabelField("请输入你要提交的信息");this.t = EditorGUILayout.TextArea(this.t); // 文本区域可以空格换行输入b = GUILayout.Toggle(b, "记住账号");b = GUILayout.Toggle(b, "记住密码");}}
  • 另一种显示窗口的方法
[MenuItem("Tools/Window")]
public static void ShowW()
{// 无法关闭MyWindow.CreateInstance<MyWindow>().ShowPopup();
}
  • 填充更多内容

4-2界面的生命周期(事件)
public class WindowEditorLife : EditorWindow
{[MenuItem("Window/MyWindow")]public static void CreatWindow(){EditorWindow.GetWindow<WIndowEditorLife>().Show();}private void OnEnable() // 当窗口可用时{Debug.Log("OnEnable ==== 1");}private void OnFocus() // 当鼠标在窗口中,获得焦点时,调用一次{Debug.Log("OnFocus ==== 2");}private void Update(){Debug.Log("所有可见窗口上每帧调用");}private void OnLostFocus() // 失去焦点时调用{Debug.Log("OnLostFocus");}private void OnGUI() // 绘制图形{Debug.Log("绘制图形");if (GUILayout.Button("关闭窗口")){this.Close();}}private void OnDisable() // 窗口不可用的时候调用{Debug.Log("OnDisable");}private void OnDestroy()  // 销毁的时候调用{Debug.Log("OnDestroy");}private void OnHierarchyChange() // 当场景层次面板发生改变的时候调用{Debug.Log("OnHierarchyChange");}private void OnValidate() // 当脚本被加载或者检视面板值备修改的时候调用{Debug.Log("OnValidate");}private void OnProjectChange() // 当工程目录更新时调用(有资源变动){Debug.Log("OnProjectChange");}private void OnSelectionChange() // 当在窗口选中某个物体时{Debug.Log("OnSelectionChange"); }private void OnInspectorUpdate()  // 窗口的更新调用,每秒10次{Debug.Log("OnInspectorUpdate");}
4-3编辑器下的UI控件
  • 滚动条

EditorGUILayout.Slider(…) 浮点数滚动条
EditorGUILayout.IntSlider(…)整数滚动条
EditorGUILayout.MinMaxSlider(…) 最小最大滚动条

         number = EditorGUILayout.Slider(number, 0, 100);number1 = EditorGUILayout.IntSlider(number1, 0, 100);EditorGUILayout.MinMaxSlider(ref number2, ref number3, 0, 100);
  • 输入框

EditorGUILayout.TextField(string) 文本输入框
EditorGUILayout.TextArea(string); 可换行的文本输入框
EditorGUILayout.PasswordField(string); 文本输入框
EditorGUILayout.ColorField(Color); 颜色输入框
EditorGUILayout.IntField(int); 整数输入
EditorGUILayout.FloatField(float); 浮点数输入
EditorGUILayout.CurveField(string,objec) // 动画曲线输入
EditorGUILayout.ObjectField(objec,typeof()) // 获取选择的物体,后面可以限制选择的物体类型
EditorGUILayout.InspectorTitlebar(bool,object) // 选择的物体放在面板

 s1 = EditorGUILayout.TextField(s1); // 文本输入s1 = EditorGUILayout.TextArea(s1); // 换行输入s1 = EditorGUILayout.PasswordField(s1); // 密码文本输入c1 = EditorGUILayout.ColorField(c1);a1 = EditorGUILayout.CurveField("动画",a1);// 选择选中的物体,类型就是后面的参数typeof(Transform)o1 = EditorGUILayout.ObjectField(o1, typeof(Transform));if (o1 != null){b = EditorGUILayout.InspectorTitlebar(b, o1); // 选择的物体放在面板Debug.Log(b);}
  • 向量

EditorGUILayout.RectField(Rect); 矩阵
EditorGUILayout.BoundsField(Bounds);XYZ距离
EditorGUILayout.Vector2Field(string, Vector2) 二维坐标
EditorGUILayout.Vector3Field(string,Vector3); 三维坐标
EditorGuILayout.Vector4Field(string,Vector4); 三维坐标(表示旋转)(增加了W)
(

        r = EditorGUILayout.RectField(r); // X,Y,width,heightb = EditorGUILayout.BoundsField(b); // 中心,大小v2 = EditorGUILayout.Vector2Field("平面位置", v2);v3 = EditorGUILayout.Vector3Field("3D位置", v3);v4 = EditorGUILayout.Vector4Field("四元数", v4);

  • 下拉菜单

EditorGUILayout.Popup(int, string[]); 字符串选择,返回字符串数组下标
EditorGUILayout.IntPopup(int,int[],string[]) 字符串选择,返回字符串对应下标的整形数组值
EditorGUILayout.EnumPopup(Enum) 枚举选择,返回枚举

 Enum e = People.man;enum People
{ man,woman
}
// 下拉菜单
index = EditorGUILayout.Popup(index, strs);
index = EditorGUILayout.IntPopup(index, strs, numbers);
e = EditorGUILayout.EnumPopup(e);
Debug.Log(e);

  • 标签、层、对象

EditorGUILayout.TagField(this.t);
EditorGUILayout.LayerField(this.layer);
EditorGUILayout.ObjectField(this.mObj, typeof(BoxCollider));

  • 展开

EditorGUILayout.Foldout(bool,string)

  s1 = "Player";s1 = EditorGUILayout.TagField(s1);// Layernumber1 = EditorGUILayout.LayerField(number1);b1 = EditorGUILayout.Foldout(b1, "点击打开"); // 展开控件if (b1){number = EditorGUILayout.Slider(number, 0, 100);o1 = EditorGUILayout.ObjectField(o1 as UnityEngine.Object, typeof(GameObject)); // 选中的游戏物体菜单}else{Debug.Log("没有任何物体");}

  • 布局分组
  • 水平分组
    EditorGUILayout.BeginHorizontal();
    EditorGUILayout.EndHorizontal();
  • 垂直分组
    EditorGUILayout.BeginVertical();
    EditorGUILayout.EndVertical();
  • Toggle分组
    EditorGUILayout.BeginToggleGroup(“选择分组”,this.mbool);
    EditorGUILayout.EndToggleGroup();
  • 滚动分组
    EditorGUILayout.BeginScrollView(this.mPos);
    EditorGUILayout.EndScrollView();
        b1 =  EditorGUILayout.BeginToggleGroup("灵敏度设置", b1);b2 = EditorGUILayout.Toggle("鼠标设置",b2);b3 = EditorGUILayout.Toggle("鼠标设置", b3);b4 = EditorGUILayout.Toggle("鼠标设置", b4);EditorGUILayout.EndToggleGroup();

####5总结:
顶部编辑器菜单:引用using UnityEditor; 使用[MenuItem()];
Inspector面板的处理:继承Editor,重写虚方法:OnInspectorGUI(),并调用(父类的此方法)base.OnInspectorGUI()
窗口的面板:继承:EditorWindow, 使用EditorWindow.GetWindow(); 调用窗口的Show()方法。

  • 欢迎购买本课程:

腾讯课堂


网易云课堂

Unity编辑器开发:2020更新相关推荐

  1. Unity编辑器开发——组件聚焦问题

    个人学习笔记,如有错误.疑问.建议,欢迎留言. 声明:本文不得以任何形式进行转载.  前言:在进行Unity编辑器开发时,经常遇到一个组件的聚焦问题:可以更改的组件,如果通过其他方式对其进行更新(即不 ...

  2. Unity编辑器开发(五):实战、开发一个AB包编辑器工具

    前言 在我们上一篇(Unity编辑器开发(四):实战.开发一个AB包编辑器工具)的结尾,我们拥有了如下图中那样的一个编辑器窗口: 接下来我们来完成最后部分,也就是包括创建AB包,清理AB包,删除AB包 ...

  3. Unity 编辑器开发实战【Custom Editor】- AudioDatabase Editor 音频库编辑器

    本文实现一个音频库的自定义编辑器,效果如图: 开始实现之前,首先简单介绍该音频库模块,音频库类Audio Database继承自Scriptable Object类,是一个可配置的资源文件: 包含的内 ...

  4. Unity编辑器开发——通过模板创建Lua脚本的两种方式(一)

    个人学习笔记,如有错误.疑问.建议,欢迎留言. 声明:本文不得以任何形式进行转载.  前言:在Unity编辑器的Project界面,可以直接右键创建C#脚本,而目前许多游戏公司使用的是tolua.xl ...

  5. Unity编辑器开发(七)——Scene界面拓展之Handles

    个人学习笔记,如有错误.疑问,欢迎留言. 声明:本文不得以任何形式进行转载.  前言:在Unity编辑器拓展时,一个很重要的部分便是在Scene界面进行拓展,通过可视化的显示UI控件,并能响应用户的操 ...

  6. 基于Unity编辑器开发技能编辑器(一)

    编辑器拓展介绍 常见的Unity编辑器拓展使用主要是创建自定义的窗体进行使用,包括剧情编辑器,动画编辑器,技能编辑器等等.最常使用的就是 EditorGUI,EditorGUILayout,GUI. ...

  7. Unity编辑器开发笔记

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 注意事项 Inspector面板一些常用C#特性 重写Inspector面板 顶部菜单栏 弹出窗口 注意事项 编辑器开发的代 ...

  8. Unity 编辑器开发实战【Custom Editor】- FSM Editor

    本文介绍如何为FSM有限状态机模块实现一个自定义编辑器面板,FSM的详细代码在上一篇文章中有介绍,链接地址: 在Unity中构建FSM有限状态机 下面是最终效果: 首先,自定义一个编辑器面板,需要用到 ...

  9. Unity 编辑器开发实战【Custom Editor】- 为UI视图制作动画编辑器

    为了更方便地为UI视图添加动画,将动画的编辑功能封装在了UI View类中,可以通过编辑器快速的为视图编辑动画.动画分为两种类型,一种是Unity中的Animator动画,该类型直接通过一个字符串类型 ...

最新文章

  1. python加颜色_Python 给屏幕打印信息加上颜色的实现方法
  2. 【Android 内存优化】Bitmap 图像尺寸缩小 ( 设置 Options 参数 | inJustDecodeBounds | inSampleSize | 工具类实现 )
  3. python 信息加密
  4. java中上传附件怎么该名称_将附件保存到Outlook中的文件夹并重命名
  5. mysql设置唯一键
  6. jenkins 使用xctool 爆出: line 6: xctool: command not found
  7. 太厉害了!2021年互联网大厂Java笔经
  8. python之质数判断
  9. 国家缩写大全 mysql_各个国家的名称缩写和时区列表
  10. 小米MIX 2最简单卡刷开发版启用root权限的方法
  11. 网易微专业Android实战教程
  12. 域自适应的理解(简单易懂)
  13. Datastage性能优化
  14. x265-1.8版本-common/contexts.h注释
  15. java高德地图api
  16. 【供参考,博主已经没有实验环境了】【中山大学东校区】【中大】【tp-link wr703n】【openwrt】【校园网inode】【无线路由】新版教程-搭载最小的认证客户端【C版oh3c】
  17. PHPWord 导出生成word
  18. Axure 使用心得分享
  19. DDNS 动态域名解析
  20. java护士排班 test 根据 1天24小时分成6班,一个护士一天上8个小时,一周上40小时,进行一周排班安排!拷贝,直接运行。

热门文章

  1. 漏洞解决方案-跨站脚本攻击
  2. Matlab 打开 Gige 工业相机连续采集数据 Bug解决
  3. 贴吧笔记本电脑选购参考攻略
  4. 面向对象编程(三) --- 抽象类和接口
  5. 计算机网络组网教程,计算机网络教程(局域网组网技术).ppt
  6. (小白)python如何微信自动加好友
  7. Java: Set String List 互转
  8. Sieve of Eratosthenes质数
  9. 华为鲲鹏云服务器发布win项目,华为DevRun第四讲,华为云鲲鹏云服务移植快速入门与实践...
  10. 学考计算机会考考点工作总结,信息技术学业水平考试工作总结.docx