ConditionalProperty 根据条件显示对应的变量

根据条件显示对应的变量.gif
所需脚本
创建 ConditionalPropertyAttribute,继承PropertyAttribute
设置该属性所需的参数
- 要参考的变量的名称(是枚举类型,最终要获取该变量当前值用于比较)
- 自身的值(上述枚举中的某个值)
创建ConditionalPropertyAttributeDrawer,继承PropertyDrawer
定义属性ConditionalProperty的规则:比较属性中参考变量的值和自身的值
- 相等:则显示该属性修饰的变量
- 不相等:不显示该属性修饰的变量
具体代码
ConditionalPropertyAttribute.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 可以放在工程的任何地方
/// 创建一个属性来修饰代码:要检查的的属性值、要与前述值对比的值
/// </summary>
public class ConditionalPropertyAttribute : PropertyAttribute
{
public string propertyToCheck;
public object compareValue;
public ConditionalPropertyAttribute(string propertyToCheck, object compareValue)
{
this.propertyToCheck = propertyToCheck;
this.compareValue = compareValue;
}
}
ConditionalPropertyAttributeDrawer.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
/// <summary>
/// 应位于“Editor”目录下,因为引用了UnityEditor。否则打包时会报错(在Unity编辑器中不会报错)
/// </summary>
// 自定义该属性的绘制形式
[CustomPropertyDrawer(typeof(ConditionalPropertyAttribute))]
public class ConditionalPropertyAttributeDrawer : PropertyDrawer
{
// 在position处将property以lable(图、文、说明文字Tooltip)的形式显示出来
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
bool isVisible = IsVisible(property);
if (isVisible)
{
EditorGUI.BeginProperty(position, label, property);
EditorGUI.PropertyField(position, property, label, true);
EditorGUI.EndProperty();
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
bool isVisible = IsVisible(property);
float height = 0;
if (isVisible)
height = EditorGUI.GetPropertyHeight(property);
return height;
}
private bool IsVisible(SerializedProperty property)
{
var conditionalPropertyAttribute = this.attribute as ConditionalPropertyAttribute;
if (conditionalPropertyAttribute == null)
Debug.LogError("ConditionPropertyAttributeDrawer couldn't cast attribute to ConditionalPropertyAttribute");
string propertyToCheckName = conditionalPropertyAttribute.propertyToCheck;
// 该值与下述实际值一致时,才在Inspector中显示其修饰的变量内容
string requiredValue = "null";
if (conditionalPropertyAttribute.compareValue != null)
requiredValue = conditionalPropertyAttribute.compareValue.ToString();
bool isVisible = true;
if (!string.IsNullOrEmpty(propertyToCheckName))
{
// 找到名为propertyToCheckName的变量,获取其(是一个枚举)当前的值
var propertyToCheck = property.serializedObject.FindProperty(propertyToCheckName);
if (propertyToCheck != null)
{
// 当前实际的值
string actualValue = propertyToCheck.enumNames[propertyToCheck.enumValueIndex];
// StringComparison.OrdinalIgnoreCase:使用序号排序规则并忽略被比较字符串的大小写,对字符串进行比较。
isVisible = string.Equals(requiredValue, actualValue, System.StringComparison.OrdinalIgnoreCase);
}
}
return isVisible;
}
}
使用方法
public enum WinCondition
{
Points,
SurviveTime,
EnemyTypeCount
}
public class Win : MonoBehaviour
{
[Header("胜利的条件")]
public WinCondition winCondition;
[ConditionalProperty("winCondition", "Points")]
public int numPointsToWin = 1500;
[Tooltip("单位:秒")]
[ConditionalProperty("winCondition", "SurviveTime")]
public float timeToSurvive = 30;
[ConditionalProperty("winCondition", "EnemyTypeCount")]
public bool eatAnyGhostToWin = true;
[ConditionalProperty("winCondition", "EnemyTypeCount")]
public int numEnemiesToEat = 10;
}
MinMax 显示最小最大值区间

设置最小最大值.gif
说明
变量使用Vector2类型,其中x表示最小值,y表示最大值
属性MinMax中设置上下限
用滑动条(EditorGUI.MinMaxSlider)显示范围
在下方用Vector4显示下限、当前允许最小值、当前允许最大值,上限(只许看,不许直接修改:GUI.enabled = false;)
使用方式
// 若showDebugValues = false,则只显示滑动条,不显示下方的具体数值
[MinMax(0, 1, showDebugValues = true)]
public Vector2 volume;
代码
MinMaxAttribute.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MinMaxAttribute : PropertyAttribute
{
public float minLimit = 0;
public float maxLimit = 1;
public bool showEditRange;
public bool showDebugValues;
public MinMaxAttribute(int min, int max)
{
minLimit = min;
maxLimit = max;
}
}
MinMaxDrawer.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(MinMaxAttribute))]
public class MinMaxDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
MinMaxAttribute minMax = attribute as MinMaxAttribute;
if (property.propertyType == SerializedPropertyType.Vector2)
{
if (minMax.showDebugValues || minMax.showEditRange)
{
position = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
}
float minValue = property.vector2Value.x;
float maxValue = property.vector2Value.y;
float minLimit = minMax.minLimit;
float maxLimit = minMax.maxLimit;
EditorGUI.MinMaxSlider(position, label, ref minValue, ref maxValue, minLimit, maxLimit);
Vector2 vec = Vector2.zero;
vec.x = minValue;
vec.y = maxValue;
property.vector2Value = vec;
if (minMax.showDebugValues || minMax.showEditRange)
{
bool isEditable = false;
if (minMax.showEditRange)
isEditable = true;
if (!isEditable)
GUI.enabled = false;
position.y += EditorGUIUtility.singleLineHeight;
Vector4 val = new Vector4(minLimit, minValue, maxValue, maxLimit);
val = EditorGUI.Vector4Field(position, "MinLimit/MinVal/MaxVal/MaxLimit", val);
GUI.enabled = false;
position.y += EditorGUIUtility.singleLineHeight;
// EditorGUI.FloatField(position, "Selected Range", maxValue - minValue);
GUI.enabled = true;
if (isEditable)
property.vector2Value = new Vector2(val.y, val.z);
}
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
MinMaxAttribute minMax = attribute as MinMaxAttribute;
float size = EditorGUIUtility.singleLineHeight;
if (minMax.showEditRange || minMax.showDebugValues)
{
size += EditorGUIUtility.singleLineHeight;
}
return size;
}
}