美文网首页
Unity 编辑器扩展六 PropertyDrawer

Unity 编辑器扩展六 PropertyDrawer

作者: 合肥黑 | 来源:发表于2021-12-10 15:08 被阅读0次

参考
Unity Editor 基础篇(六):Property Drawers
【Unity 编辑器】扩展总结七:数组或list集合的显示方式
Unity自定义ScriptableObject属性显示的三种方式
https://docs.unity.cn/cn/2019.4/Manual/editor-PropertyDrawers.html

如果想修改某种特定类型的显示,使用继承Editor的方式就会变得很麻烦,因为所有使用特定类型的asset都需要去实现一个自定义的Editor,效率非常低。这种情况就可以通过继承PropertyDrawer的方式,对指定类型的属性,进行统一显示。

一、示例
1.Serializable

在Scripts文件夹中创建两个C#脚本,分别命名为:“Person.cs”和“ShowPersonInfo.cs”

public enum Sex
{
    female,
    male
}

public class Person
{
    public string name;
    public Sex sex;
    public int age;
    public string desc;
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ShowPersonInfo : MonoBehaviour
{
    public Person persion;
}

要想给一个游戏对象挂上脚本,那么该脚本就必须继承自 MonoBehaviour ,ShowPersonInfo 就是用来做这个的。但是挂上脚本,却发现看不到Person属性。


image.png

要想将一个普通的类里的属性在Inspector面板中显示出来,那么必须将这个普通的类序列化。

public enum Sex
{
    female,
    male
}
[System.Serializable]
public class Person
{
    public string name;
    public Sex sex;
    public int age;
    public string desc;
}
image.png
2.CustomPropertyDrawer

在Editor文件夹中创建一个名为“PersonPropertiesDrawer.cs”的脚本

添加 [CustomPropertyDrawer(typeof(Persion))],指定该类是用于自定义属性的绘制。

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(Person))]
public class PersonPropertiesDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        //base.OnGUI(position, property, label);
        Debug.Log("Label:" + label.text);
        Debug.Log(position);
        while (property.NextVisible(true))
        {
            Debug.Log("OnGUI:" + property.name);
        }
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        while (property.NextVisible(true))
        {
            Debug.Log("GetPropertyHeight:" + property.name);
        }
        return base.GetPropertyHeight(property, label);
    }
}
image.png

从上面的数据可以看出如下几点:

  • OnGUI 和 GetPropertyHeight 里的 property 参数是同一个参数。该参数里存放的是 Persion 里的属性信息。
  • OnGUI 和 GetPropertyHeight 里的 Label 参数也是同一个参数,该参数里存放的是 Persion 类的类名。
  • position参数指的是需要在Inspector面板中绘制的区域信息,可以从下面两张图中简单的了解一下:
image.png

对了还有一个地方克森遗漏掉了,那就是在Inspector面板中的一行高度为 16 。

这里经过我的测试是18,使用如下代码打印一下看看就知道了

Debug.Log("label height:" + base.GetPropertyHeight(property, label));
3.自定义绘制
最终效果
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(Person))]
public class PersonPropertiesDrawer : PropertyDrawer
{
    Rect top, middleRight, middleLeft, bottom;
    SerializedProperty personName, sex, age, desc;

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        //顶部区域
        top = new Rect(position.x, position.y, position.width, position.height / 4.0f);
        //中部区域左侧
        middleLeft = new Rect(position.x,
            position.y + (position.height / 4.0f),
            position.width / 2.0f,
            position.height / 4.0f);
        //中部区域右侧
        middleRight = new Rect(position.x + position.width / 2.0f,
            position.y + (position.height / 4.0f),
            position.width / 2.0f,
            position.height / 4.0f);
        //底部区域
        bottom = new Rect(position.x,
            position.y + (position.height / 4.0f) * 2,
            position.width,
            (position.height / 4.0f) * 2);
        //获取对应的序列化属性
        personName = property.FindPropertyRelative("name");
        sex = property.FindPropertyRelative("sex");
        age = property.FindPropertyRelative("age");
        desc = property.FindPropertyRelative("desc");
        //绘制属性
        EditorGUI.PropertyField(top, personName, label);
        EditorGUI.PropertyField(middleLeft, sex);
        EditorGUI.PropertyField(middleRight, age);
        desc.stringValue = EditorGUI.TextArea(bottom, desc.stringValue);
    }

    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        return base.GetPropertyHeight(property, label) * 4;//4行
    }
}

EditorGUI.PropertyField

  • 第一个参数是该属性绘制在Inspector面板的位置
  • 第二个参数是需要绘制的序列化属性
  • 第三个参数是该属性的标签,默认为null

SerializedProperty.FindPropertyRelative
通过属性的名字获取对应的SerializedProperty

注意这个:

desc.stringValue = EditorGUI.TextArea(bottom, desc.stringValue);

如果删除desc.stringValue =,在面板上输入字符串移开焦点,输入的内容会被清空。

相关文章

网友评论

      本文标题:Unity 编辑器扩展六 PropertyDrawer

      本文链接:https://www.haomeiwen.com/subject/cdhltrtx.html