找回密码
 立即注册
查看: 623|回复: 0

Unity 编辑器扩展一 常用属性

[复制链接]
发表于 2021-12-9 19:09 | 显示全部楼层 |阅读模式
参考
Unity 编辑器扩展总结 一:编辑器开发入门
Unity 编辑器扩展总结 二:编辑器的相关特性
Unity Editor 基础篇(一):Build-In Attribute
Unity拓展编辑器入门指南
一、简单示例(编辑器扩展是做什么的)


使用Visual studio在Assets/Editor下新建项


visual studio新建项


选Editor Script

脚本名就用默认的,visual studio会自动生成一个模板代码
using UnityEditor;using UnityEngine;namespace Assets.Editor{    public class NewEditorScript1 : ScriptableObject    {        [MenuItem("Tools/MyTool/Do It in C#")]        static void DoIt()        {            EditorUtility.DisplayDialog("MyTool", "Do It in C# !", "OK", "");        }    }}


菜单上会多出一个选项

这里把: ScriptableObject去掉也没关系,关于ScriptableObject以后再做了解。

在上面的示例中,通过指定MenuItem第二个参数为true,表示DeleteValidate为此菜单的有效函数。Selection.objects.Length == 0,此菜单才生效。
using UnityEditor;using UnityEngine;namespace Assets.Editor{    public class NewEditorScript1 : ScriptableObject    {        [MenuItem("Tools/MyTool/Do It in C#", true)]        private static bool DeleteValidate()        {            if (Selection.objects.Length == 0)                return true;            else                return false;        }        [MenuItem("Tools/MyTool/Do It in C#")]        static void DoIt()        {            EditorUtility.DisplayDialog("MyTool", "Do It in C# !", "OK", "");        }    }}

选项变灰了

unity编辑器扩展#2 GUILayout、EditorGUILayout 控件整理
unity编辑器扩展#3 《Extending Unity with Editor Scripting 》笔记
一、常用属性

[MenuItem(“MyTools/test1”,false,priority)]
前两个参数上面已经解释用处,第三个参数priority是优先级,用来表示菜单按钮的先后顺序,默认值为1000。一般菜单中的分栏,数值相差大于10。
1.实现点击菜单按钮,删除场景或者Project中选中的多个对象

[MenuItem("MyTool/DeleteAllObj", true)]private static bool DeleteValidate()   {    if (Selection.objects.Length > 0)        return true;    else        return false;}[MenuItem("MyTool/DeleteAllObj",false)]private static void MyToolDelete(){    //Selection.objects 返回场景或者Project中选择的多个对象    foreach (Object item in Selection.objects)    {        //记录删除操作,允许撤销        Undo.DestroyObjectImmediate(item);    }} 2.Selection 用于获取选择的游戏物体

    Selection.activeGameObject 返回第一个选择的场景中的对象Selection.gameObjects 返回场景中选择的多个对象,包含预制体等Selection.objects 返回选择的多个对象
//遍历选择的对象,并立刻销毁foreach(object obj in Selection.objects){    DestroyImmediate(obj);}
P.S. Destroy方法会将删除的对象放在缓存中,缓存满了,才完全删除,而在编辑器未运行的时候,是没有这片缓存的,所以需要用DestroyImmediate(),立刻销毁。当然,可以直接使用Undo.DestroyObjectImmediate()来销毁对象并记录销毁操作。
3.添加快捷键

    % Ctr/Command# Shift& AltLEFT/Right/UP/DOWN    方向键F1-F2 F功能键_g    字母g

例如:[MenuItem(“MyTools/test1 %_q”)] 快捷键 Ctrl+Q
4.CONTEXT给某组件添加右键菜单选项


[MenuItem(“CONTEXT/组件名/按钮名”)]
注意CONTEXT大写
[MenuItem("CONTEXT/Rigidbody/Init")]private static void RigidbodyInit() {    //TODO}5.MenuCommand用于获取当前操作的组件


如下,给自定义的组件PlayerHealth添加右键Init按钮
[MenuItem("CONTEXT/PlayerHealth/Init")]static void Init(MenuCommand cmd){    PlayerHealth health = cmd.contex as PlayerHealth;}6.ContextMenu、ContextMenuItem


给某组件添加右边小齿轮菜单选项
[ContextMenu("FunctionName")]public void FunctionName(){    //ToDo}
给某属性添加右键菜单选项
[ContextMenuItem("Handle", "HandleHealth")]public float health;private void HandleHealth(){    //ToDo}
P.S. 这两个特性是在UnityEngine命名空间下的,而不像其他[MenuItem]、Selection是在UnityEditor下的。
7.常用的属性特性

    [Range(0,100)] //限制数值范围[Multiline(3)] //字符串多行显示[TextArea(2,4)] //文本输入框[SerializeField] //序列化字段,主要用于序列化私有字段[NonSerialized] //反序列化一个变量,并且在Inspector上隐藏[HideInInspector] //public变量在Inspector面板隐藏[FormerlySerializedAs(“Value1”)] //当变量名发生改变时,可以保存原来Value1的值[ContextMenu(“TestBtn”)] //组件右键菜单按钮[ContextMenuItem(“Reset Value”,“Reset”)] //定义属性的右键菜单[Header(“Header Name”)] //加粗效果的标题[Space(10)] //表示间隔空间,数字越大,间隔越大[Tooltip(“Tips”)] //显示字段的提示信息[ColorUsage(true)] //显示颜色面板

image.png


通过Space进行布局分割

8.常用的方法特性

    [DrawGizmo] //用于Gizmos渲染,将逻辑与调试代码分离[MenuItem] //添加菜单项
9.常用的类的特性

    [Serializable] //序列化一个类,作为一个子属性显示在监视面板[RequireComponent(typeof(Animator))] //挂载该类的对象,必须要有Animator组件[DisallowMultipleComponent] //不允许挂载多个该类或其子类[ExecuteInEditMode] //允许脚本在编辑器未运行的情况下运行[CanEditMultipleObjects] //允许当选择多个挂有该脚本的对象时,统一修改值[AddComponentMenu] //可以在菜单栏Component内添加组件按钮[CustomEditor] //要自定义编辑器就要加这个特性[CustomPropertyDrawer] //用于绘制自定义PropertyDrawer的特性[SelectionBase] //选择在场景视图中使用此属性的组件对象,即不会误选中子物体

P.S. 多个特性可以用逗号隔开,例如:[SerializeField, Range(0,5)]

我们既想保证类的某个字段不被其他的类访问修改,又想在Inspector视窗中修改这个字段的值的话,就可以采用private +[SerializeField]属性的方案。
[SerializeField]private int privateInt;

image.png

10.AddComponentMenu


AddComponentMenu 属性允许将一个脚本添加到 Component 菜单中,然后你便可以通过 Component ->(你设置的名字)为一个选中的游戏对象创建该脚本
[AddComponentMenu("Learn/Test")]public class Test1 : MonoBehaviour

image.png

11.[RequireComponent(typeof(Animator))]


RequireComponent()属性会自动帮你添加你需要的组件,如果已经存在则不再重复添加,且不能移除
[AddComponentMenu("Learn/Test")][RequireComponent(typeof(Rigidbody))]public class Test1 : MonoBehaviour{

尝试移除失败

提示:经过测试,我发现一个问题,如果脚本已经挂在物体身上,然后再修改脚本,添加 RequireComponent 属性的话,完全不起作用,因此建议大家在用此属性的时候要注意。
12.ContextMenu


ContextMenu()属性允许添加一个命令到该组件上,你可以通过右键或者点击设置图标来调用到它(一般用于函数),且是在非运行状态下执行该函数,如下所示:
[AddComponentMenu("Learn/Test")][RequireComponent(typeof(Rigidbody))]public class Test1 : MonoBehaviour{    public Text Text1;    public bool myBool;    public string myString;    [ContextMenu("OutputInfo")]    void OutputInfo()    {        Debug.Log("outputinfo");    }}

image.png

13.HelpURL


HelpURL()提供一个自定义的文档链接,点击组件上的文档图标既能打开到你指定的链接,如下所示:
[HelpURL("http://www.baidu.com")][AddComponentMenu("Learn/Test")][RequireComponent(typeof(Rigidbody))]public class Test1 : MonoBehaviour

image.png

14.Range、Multiline、header


Range()属性用于将一个值指定在一定的范围内,并在Inspector面板中为其添加滑块;Multiline()属性用于给 string 类型添加多行输入;header()属性用于添加属性的标题,具体操作如下所示:
public class Test1 : MonoBehaviour{    public Text Text1;    public bool myBool;    [Header("BaseInfo")]    [Multiline(5)]    public string myString;    [Range(-2, 2)]    public int age;

image.png

15.Tooltip、Space


Tooptip()属性用于在 Inspector 面板中,当鼠标停留在设置了Tooptip()的属性添加指定的提示;Space()用于为在 Inspector 面板两属性之间添加指定的距离,如下所示:
    [Range(-2, 2)]    public int age;    [Space(100)]    [Tooltip("用于设置性别")]    public string sex;

image.png

二、编辑器相关文件夹介绍

1.Editor

    该文件夹可以放在项目的任何文件夹下,可以有多个"Editor"文件夹。编辑器扩展相关的脚本都要放在该文件夹内,该文件夹中的脚本只会对Unity编辑器起作用。项目打包的时候,不会被打包到项目中。如果编辑器相关脚本不放在该文件夹中,打包项目可能会出错。如果非要有些编辑器相关脚本不放在该文件夹中,需要在该类的前后加上UNITY_EDITOR的宏定义
2.Editor Default Resources

    该文件夹需要放在Assets根目录下,用来存储编辑器所需要的图片等资源,书写的时候需要注意中间有空格隔开。此文件夹也不会被打包,访问方法为:EditorGUIUtility.Load()当然,也可以在Editor文件夹内创建一个Resources文件夹,将相关资源放在该文件夹内,通过Resources.Load()获取资源,也是可以的
3.Gizmos

    该文件夹也需要放在Assets根目录下,可以用来存放Gizmos.DrawIcon()的图片资源
4.一般继承MonoBehaviour的脚本都放在Assets/Scripts文件夹里,而使用using UnityEditor;这个命名空间的脚本都放在Assets/Editor文件夹里。本系列文章后续例子中的代码,不再重复说明此点。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-23 01:24 , Processed in 0.091321 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表