您当前的位置: 首页 >  unity

CoderZ1010

暂无认证

  • 2浏览

    0关注

    168博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

七、Unity编辑器开发之PropertyDrawer

CoderZ1010 发布时间:2021-05-14 09:45:26 ,浏览量:2

PropertyDrawer允许我们控制一个属性的Inspector检视面板的GUI如何绘制。

首先看几个Unity中内置的PropertyDrawers:

[Range(0, 20)]
public int intValue = 10;

[Header("名称")]
public string nameStr;

[SerializeField]
private float floatValue = 10f;

如图所示,Range可以限制intValue的取值范围0~20,Header可以给字段做一些描述或备注,SerializeField允许我们讲一个Private私有字段同Public字段一样显示在Inspector检视面板上。

那么如何自定义一个PropertyDrawer?以一个Time特性为例:

[Time]
public float time = 473.35f;

我们希望将一个float类型的描述时间的字段在Inspector面板上以00:00时间格式进行显示:

首先先定义Time特性:

using UnityEngine;

namespace SK.Framework
{
    /// 
    /// 时间特性
    /// 
    public sealed class TimeAttribute : PropertyAttribute
    {
        /// 
        /// 显示小时
        /// 
        public readonly bool displayHours;
        /// 
        /// 显示毫秒
        /// 
        public readonly bool displayMillseconds;
        /// 
        /// 构造函数 
        /// 
        /// 显示小时
        /// 显示毫秒
        public TimeAttribute (bool displayHours = false, bool displayMillseconds = false)
        {
            this.displayHours = displayHours;
            this.displayMillseconds = displayMillseconds;
        }
    }
}

有了TimeAttribute后,我们来自定义它如何在Inspector上进行绘制:

需要在Editor文件夹中创建TimeDrawer类,引入UnityEditor命名空间并继承PropertyDrawer

然后Override重写OnGUI方法来实现绘制,GetPropertyHeight用来定义绘制属性的高度

using System;
using UnityEngine;
using UnityEditor;

namespace SK.Framework
{
    /// 
    /// 时间特性绘制
    /// 
    [CustomPropertyDrawer(typeof(TimeAttribute))]
    public sealed class TimeDrawer : PropertyDrawer
    {
        public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
        {
            if(property.propertyType == SerializedPropertyType.Float)
            {
                property.floatValue = EditorGUI.FloatField(new Rect(position.x, position.y, position.width * 0.6f, position.height), label, property.floatValue);
                EditorGUI.LabelField(new Rect(position.x + position.width * 0.6f, position.y, position.width * 0.4f, position.height), GetTimeFormat(property.floatValue));
            }
            else
            {
                EditorGUI.HelpBox(new Rect(position.x, position.y, position.width, position.height), "只支持float类型属性", MessageType.Error);
            }
        }

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

        private string GetTimeFormat(float secondsTime)
        {
            TimeAttribute ta = attribute as TimeAttribute;
            //显示小时不显示毫秒
            if (ta.displayHours && !ta.displayMillseconds)
            {
                int l = Convert.ToInt32(secondsTime);
                int hours = l / 3600;
                int minutes = l % 3600 / 60;
                int seconds = l % 3600 % 60;
                return string.Format("({0:D2}:{1:D2}:{2:D2} [hh:mm:ss])", hours, minutes, seconds);
            }
            //显示毫秒不显示小时
            else if(!ta.displayHours && ta.displayMillseconds)
            {
                int l = Convert.ToInt32(secondsTime * 1000);
                int minutes = l / 60000;
                int seconds = l % 60000 / 1000;
                int millSeconds = l % 60000 % 1000;
                return string.Format("({0:D2}:{1:D2}.{2:D3} [mm:ss.fff)]", minutes, seconds, millSeconds);
            }
            //既显示小时也显示毫秒
            else if (ta.displayHours && ta.displayMillseconds)
            {
                int l = Convert.ToInt32(secondsTime * 1000);
                int hours = l / 3600000;
                int minutes = l % 3600000 / 60000;
                int seconds = l % 3600000 % 60000 / 1000;
                int millSeconds = l % 3600000 % 60000 % 1000;
                return string.Format("({0:D2}:{1:D2}:{2:D2}.{3:D3} [hh:mm:ss.fff)]", hours, minutes, seconds, millSeconds);
            }
            //既不显示小时也不显示毫秒
            else
            {
                int l = Convert.ToInt32(secondsTime);
                int minutes = l / 60;
                int seconds = l % 60;
                return string.Format("({0:D2}:{1:D2}) [mm:ss]", minutes, seconds);
            }
        }
    }
}

TimeAttribute可以控制是否显示小时、是否显示毫秒:

[Time(true, true)]
public float time1 = 473.35f;
[Time(true, false)]
public float time2 = 473.35f;
[Time(false, true)]
public float time3 = 473.35f;
[Time]
public float time4 = 473.35f;
[Time]
public int time5 = 0;

关注
打赏
1653184800
查看更多评论
立即登录/注册

微信扫码登录

0.2804s