阅读国外Coder教程时的笔记,Object Management篇(七)CustomPropertyDrawer

原文地址:https://catlikecoding.com/unity/tutorials/object-management/multiple-scenes/
阅读国外Coder教程时的笔记,Object Management篇(一)
阅读国外Coder教程时的笔记,Object Management篇(二)
阅读国外Coder教程时的笔记,Object Management篇(三)
阅读国外Coder教程时的笔记,Object Management篇(四)
阅读国外Coder教程时的笔记,Object Management篇(五)
阅读国外Coder教程时的笔记,Object Management篇(六)

1.如何在Inspector面板上绘制UI
下图是我们在Inspector面板上看到的常规界面,枚举+结构体嵌套
在这里插入图片描述
代码:

    [System.Serializable]
    public struct SpawnConfiguration {
        public enum MovementDirection
        {
            Forward,
            Upward,
            Outward,
            Random
        }
        public MovementDirection movementDirection;
        public CreatingFloatRange speed;
        public CreatingFloatRange angularSpeed;
        public CreatingFloatRange scale;
        public ColorRangeHSV color;
    }
    //嵌套结构体
	[System.Serializable]
	public struct CreatingFloatRange 
	{
	    public float min, max;
	    public float RandomValueInRange {
	        get {
	            return Random.Range(min,max);
	        }
	    }
	}

这样看上去是不是有点不太简洁?再看下图是不是就简洁多了。
在这里插入图片描述
以上主要通过在Editor文件夹下新建一个绘制UI的脚本实现。
在这里插入图片描述
代码如下,意思有点像用代码设置他们的位置关系:

using UnityEngine;
using UnityEditor;

[CustomPropertyDrawer(typeof(CreatingFloatRange))]
public class CreatingFloatRangeDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        int originalIndentLevel = EditorGUI.indentLevel;
        float originalLabelWidth = EditorGUIUtility.labelWidth;
        EditorGUI.BeginProperty(position,label,property) ;
        position = EditorGUI.PrefixLabel(position,GUIUtility.GetControlID(FocusType.Passive),label);
        position.width = position.width / 2f;
        EditorGUIUtility.labelWidth = position.width / 2f;
        EditorGUI.indentLevel = 1;
        EditorGUI.PropertyField(position,property.FindPropertyRelative("min"));
        position.x += position.width;
        EditorGUI.PropertyField(position, property.FindPropertyRelative("max"));
        EditorGUI.EndProperty();
        EditorGUI.indentLevel = originalIndentLevel;
        EditorGUIUtility.labelWidth = originalLabelWidth;
    }
}

对于最大值和最小值固定的范围,比如说色值。我们可以设置程下图所示:
在这里插入图片描述
原理和上面的相同,但是稍微麻烦一点。
首先把常规的Range类替换程自定义的范围类,这个类必须继承PropertyAttribute类。比如:

using UnityEngine;

public class FloatRangeSliderAttribute : PropertyAttribute
{
    public float Min { get; private set; }
    public float Max { get; private set; }

    public FloatRangeSliderAttribute(float min, float max) {
        if (max < min) {
            max = min;
        }
        Min = min;
        Max = max;
    }
}
//这里可以使用自定义的范围类
    [FloatRangeSlider(0f,1f)]
    public CreatingFloatRange hue, saturation, value;

然后和开始一样,在Editor文件下新建一个绘制UI的脚本,具体如下:

using UnityEditor;
using UnityEngine;

[CustomPropertyDrawer(typeof(FloatRangeSliderAttribute))]
public class FloatRangeSliderDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        int originalIndentLevel = EditorGUI.indentLevel;
        EditorGUI.BeginProperty(position,label,property);
        position = EditorGUI.PrefixLabel(position,GUIUtility.GetControlID(FocusType.Passive),label);
        EditorGUI.indentLevel = 0;
        SerializedProperty minProperty = property.FindPropertyRelative("min");
        SerializedProperty maxProperty = property.FindPropertyRelative("max");
        float minValue = minProperty.floatValue;
        float maxValue = maxProperty.floatValue;
        float fieldWidth = position.width / 4f - 4f;
        float sliderWidth = position.width / 2f;
        position.width = fieldWidth;
        minValue = EditorGUI.FloatField(position,minValue);
        position.x += fieldWidth+4f;
        position.width = sliderWidth; 
        FloatRangeSliderAttribute limit = attribute as FloatRangeSliderAttribute;
        EditorGUI.MinMaxSlider(position,ref minValue,ref maxValue,limit.Min,limit.Max);
        position.x += sliderWidth+4f;
        position.width = fieldWidth;
        maxValue = EditorGUI.FloatField(position,maxValue);
        if (minValue < limit.Min)
        {
            minValue = limit.Min;
        }
        else if (minValue > limit.Max) {
            minValue = limit.Max;
        }
        if (maxValue < minValue)
        {
            maxValue = minValue;
        }
        else if (maxValue > limit.Max) {
            maxValue = limit.Max;
        }
        minProperty.floatValue = minValue;
        maxProperty.floatValue = maxValue;
        EditorGUI.EndProperty();
        EditorGUI.indentLevel = originalIndentLevel;
    }
}

具体详细就不介绍了,可以当成一个工具使用,只要替换FindPropertyRelative里的参数就好了。

以上,希望可以帮助到大家学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值