自己常用的一个预制功能模块,用到这个开关显示的功能,但又不想依赖Odin。
一个是自己穷,用不起Odin,二是如果我的包给别人用,依赖的太多而且还是收费的,会不会被人炸掉祖坟。
一、效果演示

在脚本的观察面板上,通过一些变量开关,显示和隐藏某些字段。
目前Unity没有这个Attribute,所以要么你用诸如Odin,要么自己用AI搓一个
二、需求来源
自己常用的一个预制功能模块,用到这个开关显示的功能,但又不想依赖Odin。
一个是自己穷,用不起Odin,二是如果我的包给别人用,依赖的太多而且还是收费的,会不会被人炸掉祖坟。
三、功能脚本组成
脚本1,Editor下:ConditionalFieldDrawer.cs,注意,必须放在Editor下
脚本2,Runtime下:ConditionalFieldAttribute.cs,不能放在Editor下
脚本3,测试脚本:Demo.cs
挂载后到物体并测试:
四、源码
1、ConditionalFieldDrawer.cs 清单
csharp
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(ConditionalFieldAttribute))]
public class ConditionalFieldDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
ConditionalFieldAttribute condHAtt = (ConditionalFieldAttribute)attribute;
// 找到比较的字段
SerializedProperty comparedField = property.serializedObject.FindProperty(condHAtt.ComparedPropertyName);
if (comparedField != null && comparedField.propertyType == SerializedPropertyType.Boolean)
{
bool enabled = comparedField.boolValue == condHAtt.ExpectedValue;
if (enabled)
{
EditorGUI.PropertyField(position, property, label, true);
}
}
else
{
// 如果字段没找到,正常显示
EditorGUI.PropertyField(position, property, label, true);
}
}
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
ConditionalFieldAttribute condHAtt = (ConditionalFieldAttribute)attribute;
SerializedProperty comparedField = property.serializedObject.FindProperty(condHAtt.ComparedPropertyName);
if (comparedField != null && comparedField.propertyType == SerializedPropertyType.Boolean)
{
bool enabled = comparedField.boolValue == condHAtt.ExpectedValue;
return enabled ? EditorGUI.GetPropertyHeight(property, label, true) : 0;
}
return EditorGUI.GetPropertyHeight(property, label, true);
}
}
2、ConditionalFieldAttribute.cs 清单
csharp
using System;
using UnityEngine;
[AttributeUsage(AttributeTargets.Field, AllowMultiple = true, Inherited = true)]
public class ConditionalFieldAttribute : PropertyAttribute
{
public string ComparedPropertyName { get; private set; }
public bool ExpectedValue { get; private set; }
public ConditionalFieldAttribute(string comparedPropertyName, bool expectedValue = true)
{
this.ComparedPropertyName = comparedPropertyName;
this.ExpectedValue = expectedValue;
}
}
3、Demo.cs 清单
csharp
using UnityEngine;
public class ConditionalFieldTest : MonoBehaviour
{
[Header("总开关")]
public bool masterSwitch;
[Header("子选项,只在 masterSwitch == true 时显示")]
[ConditionalField(nameof(masterSwitch), true)]
public bool optionA;
[ConditionalField(nameof(masterSwitch), true)]
public bool optionB;
[Header("反向测试:只有当 masterSwitch == false 时才显示")]
[ConditionalField(nameof(masterSwitch), false)]
public string hiddenMessage = "当 masterSwitch == false 时才看得见";
[Header("多层嵌套测试")]
public bool subSwitch;
[ConditionalField(nameof(subSwitch), true)]
public int subValue;
}
五、致谢:
感谢GPT,从前的搜索时代是信息平权,现在的GPT时代是知识平权。
网友说:三天不学习,赶不上GPT。