扩展Project视图

扩展右键菜单

// 排序数越小,排序越靠前
[MenuItem("Assets/右键菜单路径", false, 排序数)]
static void MyTools(){
    // 点击后,触发的逻辑
}

Hierarchy视图

Inspector视图

Scene视图

Game视图

导航栏

编辑器特性

HideInInspector

隐藏公共成员变量,防止Inspector面板的值影响到它

应用:不想被检视面板中看到,但需要被其他类引用

[HideInInspector]
public int ID = 99;

SerializeField

私有变量在Inspector面板中出现

[SerializeField]
private string Name;

Serializable

在检视面板中显示类

[Serializable]
public class Numerical
{
    public float Atk;
    public float Def;
}

Space

在当前成员变量上方留50像素的空白区域

[Space(50)]
public int Age;

在当前成员变量上方添加一个名字

[Header("玩家名字")]
public string name;

Tooltip

为age变量添加,鼠标悬浮2秒后,提示文字

[Tooltip("不要填写大于100岁的年龄")]
public int age;

Range

给数值设定指定范围

[Range(0, 150)]
public int Age;

Multiline

指定拥有几行输入框

[Multiline(5)]
public string content;

TextArea

文本区域,TextArea(5, 10),默认显示5行,最大10行)

[TextArea(5, 10)]
public string Description;

ContextMenu

给小齿轮添加一个回调函数

在挂载脚本右边的的三个点,可以点击对应的名字,执行函数

[ContextMenu("输出")]
public void Print()
{
    Debug.Log("输出内容");
}

ContextMenuItem

ContextMenuItem(“打印国家”, “OutCountry”),

第一个参数:添加右键菜单,第二个参数:右键点击的回调函数的名字

[ContextMenuItem("输出国家", "OutCountry")]
[Tooltip("右键看看")]
public string Country;

public void OutCountry()
{
    Debug.Log(Country);
}

AddComponentMenu

将组件添加到AddComponentMenu菜单栏上,并且组件的名字会显示组件名

// 参数一:分类名/组件名
// 参数二:列表中显示的顺序
[AddComponentMenu("自定义控制器/玩家控制器", 1)]

PropertyDrawer

PropertyDrawer 是 Unity 中用于自定义 Inspector 面板属性显示的工具。它能让你在不修改原有代码的情况下,更直观、更高效地调整组件参数。

比如:在 Inspector 面板把输入框变成滑动条、颜色选择器等。

适用于:

  • 你想让某个变量的输入更直观(如用滑块代替手动输入数值)。

  • 想根据变量的值动态显示不同内容(如根据布尔值显示/隐藏其他字段)。

PropertyDrawer基础使用

比如实现如下的操作

public class Test01 : MonoBehaviour
{
    [MyAttribute]
    public string text;
}


public class MyAttribute : PropertyAttribute
{
    
}

// 1. 必须要继承 PropertyDrawer 类
// 2. 将其绑定到类或特性上
// [CustomPropertyDrawer(typeof(YourClass))] 绑定到你的类上
// [CustomPropertyDrawer(typeof(RangeAttribute))] 绑定到你自己定义的特性上
[CustomPropertyDrawer(typeof(MyAttribute))]
public class MyPropertyDrawer : PropertyDrawer
{
    // 绘制属性的 GUI
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // Rect position: 控件的位置和大小(相对于父控件的起始坐标)
        //  position.x 和 position.y 是绘制的起始坐标
        //  position.width 和 position.height 是控件的宽度和高度
        // SerializedProperty property: 当前数据的数据
        // GUIContent label: 属性的标签(显示的内容)
        
        // 绘制字段
        property.stringValue = "字段的内容";
        label = new GUIContent("自定义字段");
        EditorGUI.PropertyField(position, property, label);
    }
}

Rect position

作用:定义当前属性在 Inspector 面板中的绘制区域(位置和大小)

  • position.xposition.y 是绘制的起始坐标(相对于父控件)。

  • position.widthposition.height 是控件的宽度和高度。

SerializedProperty property

作用:表示当前正在绘制的属性,可以通过它读取或修改属性值

  • 使用 property.FindPropertyRelative("子字段名") 访问嵌套属性。

  • 通过 property.intValue, property.floatValue, property.objectReferenceValue 等获取具体值。

  • 修改值后需要调用 property.serializedObject.ApplyModifiedProperties() 提交更改。

GUIContent label

作用:控制属性在 Inspector 中的显示名称和提示信息

  • label.text 是字段的名称(可通过 [SerializeField] private string Name { get; set; } 自定义)。

  • label.tooltip 是鼠标悬停时的提示信息

应用场景

1. 实现范围限制

public class Test01 : MonoBehaviour
{
    [My(1,10,2)]
    public float text;
}

public class MyAttribute : PropertyAttribute
{
    public float Min, Max, Step;

    public MyAttribute(float min, float max, float step)
    {
        this.Min = min;
        this.Max = max;
        this.Step = step;
    }
}

[CustomPropertyDrawer(typeof(MyAttribute))]
public class MyPropertyDrawer : PropertyDrawer
{

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        MyAttribute myAttribute = (MyAttribute)attribute;
        
        // 1. 滑动条的位置大小
        // 2. 滑动条的标签
        // 3. 滑动条的初始值
        // 4. 滑动条的最小值
        // 5. 滑动条的最大值
        // 返回的值用户选中的值
        float value = EditorGUI.Slider(position, label, property.floatValue, myAttribute.Min, myAttribute.Max);
        
        // 调整为某个步长的倍数
        value = Mathf.Round(value / myAttribute.Step) * myAttribute.Step;
        property.floatValue = value;
    }
}

2. 修改标签的显示名称

public class Test01 : MonoBehaviour
{
    [My("文本标签")]
    public string text;
}

public class MyAttribute : PropertyAttribute
{
    public string showName;
    public MyAttribute(string name)
    {
        showName = name;
    }
}

[CustomPropertyDrawer(typeof(MyAttribute))]
public class MyPropertyDrawer : PropertyDrawer
{

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        MyAttribute myAttribute = (MyAttribute)attribute;
        label.text = myAttribute.showName;
        label.tooltip = "悬停提示"; // 可以设置悬停提示
        EditorGUI.PropertyField(position, property, label);
    }
}

3. 下拉菜单

public class Test01 : MonoBehaviour
{
    [My]
    public string text;
}

public class MyAttribute : PropertyAttribute
{
    
}

[CustomPropertyDrawer(typeof(MyAttribute))]
public class MyPropertyDrawer : PropertyDrawer
{
    private GUIContent[] gcs = new GUIContent[]
    {
        new GUIContent("Value"),
        new GUIContent("Color"),
        new GUIContent("Alpha")
    };

    private int selectedIndex;

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        MyAttribute myAttribute = (MyAttribute)attribute;
        
        // 1. 位置和大小
        // 2. 标签
        // 3. 当前选中的选项索引
        // 4. 字符串数组
        selectedIndex = EditorGUI.Popup(position, label, selectedIndex, gcs);
        if (EditorGUI.EndChangeCheck())
        {
            property.stringValue = gcs[selectedIndex].text;
            Debug.Log(property.stringValue);
        }
    }
}