Unity编辑器拓展PropertyDrawer——Editor绘制偷懒神器

写在前面

我们在使用UnityEditor自定义属性面板时,大多的时候都是直接使用继承Editor的方式实现,一个脚本类写一个Editor类,但是有很多非MonoBehaviour的类,会需要在不同的脚本上使用,这个时候需求就来了,每一个都要重复写那也太麻烦了,这个时候就可以用PropertyDrawer了。

我使用的Unity版本:Unity 2020.3.10
在这里插入图片描述

总结

PropertyDrawer的两大主要作用:
1. 用于自定义绘制可序列化的类或结构体
有需要自定义显示的又会可能在多个脚本中使用到的类或结构体都可以使用PropertyDrawer来实现,PropertyDrawer如其名,就像一个专门的属性绘制器一样,对一个类或结构体进行自定义属性绘制后,当脚本在属性面板上显示该属性时,就会调用到该自定义的绘制,不用我们再写Editor脚本去单独绘制,所以省去了大量的工作
2. 搭配PropertyAttribute可自定义Attribute
相信大家平常都有用过诸如【Header】【ToolTip】之类的Attribute,而通过PropertyAttribute+PropertyDrawer就可以自定义自己的Attribute

自定义绘制可序列化的类或结构体

这里我们使用书,书单的类来示例这个功能
Book就是我们要进行自定义绘制的类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum BookType
{
    Novel,
    Science,
    Life,
    Tool,
}
[System.Serializable]
public class Book
{
    public string name;
    public BookType type;
    public string overview;
}
public class BookList : MonoBehaviour
{
    public Book currentRead;
    public Book[] readList;
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(Book))]
public class BookDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginProperty(position, label, property);
        //FocusType.Passive 使用Tab键切换时不会被选中,FocusType.Keyboard 使用Tab键切换时会被选中,很显然这里我们不需要label能被选中进行编辑 
        position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
        //不让indentLevel层级影响到同一行的绘制,因为PropertyDrawer在很多地方都有可能被用到,可能出现嵌套使用
        var indent = EditorGUI.indentLevel;
        EditorGUI.indentLevel = 0;
        var nameRect = new Rect(position.x, position.y, 50, position.height);
        var typeRect = new Rect(position.x + 55, position.y, 60, position.height);
        var overviewRect = new Rect(position.x + 120, position.y, position.width - 90, position.height);
        EditorGUI.PropertyField(nameRect, property.FindPropertyRelative("name"), GUIContent.none);
        EditorGUI.PropertyField(typeRect, property.FindPropertyRelative("type"), GUIContent.none);
        EditorGUI.PropertyField(overviewRect, property.FindPropertyRelative("overview"), GUIContent.none);
        EditorGUI.indentLevel = indent;
        EditorGUI.EndProperty();
    }
}

自定义前后对比
在这里插入图片描述
后来我们又有一个书库的类,这个时候就不用再写Editor类了,直接就有效果

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class BookTypeList
{
    public string name;
    public Book[] bookList;
}
public class BookLibrary : MonoBehaviour
{
    [SerializeField]
    public List<BookTypeList> library;
}

在这里插入图片描述

PropertyAttribute+PropertyDrawer自定义Attribute

自定义Attribute可以让我们定义很多非常方便的Attribute去使用,我们这里实现一个Label的Attribute,经常策划会抱怨看不懂脚本上的参数,有了LabelAttribute,汉化工作就方便太多了
大家可以根据自己的需要大胆发挥创作
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LabelAttribute : PropertyAttribute
{
    public string name;
    public LabelAttribute(string name)
    {
        this.name = name;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(LabelAttribute))]
public class LabelAttributeDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        LabelAttribute labelAttribute = this.attribute as LabelAttribute;
        EditorGUI.PropertyField(position, property, new GUIContent(labelAttribute.name));
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LabelAttributeTest : MonoBehaviour
{
    [LabelAttribute("书籍名称")]
    public string bookName;
    [LabelAttribute("书籍类型")]
    public BookType bookType;
    [LabelAttribute("书籍价格")]
    public float price;
}

还未搞明白的

PropertyDrawer还有一个可重写的方法 CreatePropertyGUI,但不知如何用,具体用在哪里?目前还没有使用到,后续碰到再看,目前根据官方文档还是搞不明白。

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;
[CustomPropertyDrawer(typeof(Book))]
public class BookDrawerUIE : PropertyDrawer
{
    public override VisualElement CreatePropertyGUI(SerializedProperty property)
    {
        var container = new VisualElement();
        var nameField = new PropertyField(property.FindPropertyRelative("name"));
        var typeField = new PropertyField(property.FindPropertyRelative("type"));
        var overviewField = new PropertyField(property.FindPropertyRelative("overview"));
        container.Add(nameField);
        container.Add(typeField);
        container.Add(overviewField);
        return container;
    }
}
  • 8
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Unity编辑器拓展Editor Extension)可以通过自定义的脚本来扩展Unity编辑器的功能和界面,以满足特定项目的需求。通过编辑器拓展,开发者可以创建自定义的编辑器窗口、工具栏按钮、菜单项、检视面板等,来增强Unity编辑器的功能和流程。 要创建一个Unity编辑器拓展,你可以使用C#编写一个继承自Editor类的脚本。这个脚本可以通过Unity的Inspector面板来设置相关的属性和行为。以下是一个简单的示例: ```csharp using UnityEngine; using UnityEditor; public class MyEditorExtension : EditorWindow { [MenuItem("Custom Tools/My Editor Window")] public static void OpenWindow() { // 创建并打开一个自定义的编辑器窗口 MyEditorExtension window = (MyEditorExtension)EditorWindow.GetWindow(typeof(MyEditorExtension)); window.Show(); } private void OnGUI() { // 在编辑器窗口中绘制UI元素 GUILayout.Label("Hello, I am a custom editor window!"); if (GUILayout.Button("Click Me")) { Debug.Log("Button clicked!"); } } } ``` 上述代码创建了一个自定义的编辑器窗口,并在窗口中绘制了一个标签和一个按钮。通过在Unity编辑器中点击"Custom Tools"菜单下的"My Editor Window",可以打开这个自定义的编辑器窗口。 除了编辑器窗口,你还可以通过继承Editor类来创建自定义的检视面板、菜单项等。Unity官方文档中有更详细的教程和示例,可以帮助你更深入地了解和使用Unity编辑器拓展
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值