给你的Unity编辑器添加实现类似 Odin 的 条件显示字段 (ShowIf/HideIf) 功能
自己常用的一个预制功能模块,用到这个开关显示的功能,但又不想依赖Odin。
一个是自己穷,用不起Odin,二是如果我的包给别人用,依赖的太多而且还是收费的,会不会被人炸掉祖坟。
一、效果演示
在脚本的观察面板上,通过一些变量开关,显示和隐藏某些字段。
目前Unity没有这个Attribute,所以要么你用诸如Odin,要么自己用AI搓一个
二、需求来源
自己常用的一个预制功能模块,用到这个开关显示的功能,但又不想依赖Odin。
一个是自己穷,用不起Odin,二是如果我的包给别人用,依赖的太多而且还是收费的,会不会被人炸掉祖坟。
三、功能脚本组成
脚本1,Editor下:ConditionalFieldDrawer.cs,注意,必须放在Editor下
脚本2,Runtime下:ConditionalFieldAttribute.cs,不能放在Editor下
脚本3,测试脚本:Demo.cs
挂载后到物体并测试:
四、源码
1、ConditionalFieldDrawer.cs 清单
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 清单
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 清单
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。